Google Analytics for WordPress by MonsterInsights - Version 7.8.0

Version Description

= 7.0.0 =

This is a major release. Please back up your site before upgrading.

= 6.0.0 =

This is a major release. Please back up your site before upgrading.

Download this release

Release Info

Developer chriscct7
Plugin Icon 128x128 Google Analytics for WordPress by MonsterInsights
Version 7.8.0
Comparing to
See all releases

Code changes from version 7.7.1 to 7.8.0

Files changed (77) hide show
  1. README.md +162 -162
  2. assets/css/admin-common.css +56 -56
  3. assets/css/admin-common.min.css +1 -1
  4. assets/css/images/index.php +3 -3
  5. assets/css/images/logo.png +0 -0
  6. assets/css/images/logo@2x.png +0 -0
  7. assets/css/images/mascot.png +0 -0
  8. assets/css/images/mascot@2x.png +0 -0
  9. assets/css/index.php +3 -3
  10. assets/fonts/README.md +17 -17
  11. assets/fonts/index.php +3 -3
  12. assets/images/chart.png +0 -0
  13. assets/images/down-green.png +0 -0
  14. assets/images/down-green@2x.png +0 -0
  15. assets/images/down.png +0 -0
  16. assets/images/down@2x.png +0 -0
  17. assets/images/index.php +3 -3
  18. assets/images/plugin-om.png +0 -0
  19. assets/images/plugin-smtp.png +0 -0
  20. assets/images/plugin-wpforms.png +0 -0
  21. assets/images/question-mark.png +0 -0
  22. assets/images/up-red.png +0 -0
  23. assets/images/up-red@2x.png +0 -0
  24. assets/images/up.png +0 -0
  25. assets/images/up@2x.png +0 -0
  26. assets/images/woo-edd-upsell.png +0 -0
  27. assets/index.php +3 -3
  28. assets/js/admin-common.js +24 -24
  29. assets/js/frontend.js +600 -600
  30. assets/js/index.php +3 -3
  31. assets/lib/index.php +3 -3
  32. assets/lib/pandora/class-am-dashboard-widget-extend-feed.php +130 -130
  33. assets/lib/pandora/class-am-deactivation-survey.php +342 -342
  34. assets/lib/pandora/class-am-notification.php +472 -472
  35. googleanalytics.php +747 -808
  36. includes/admin/admin.php +483 -485
  37. includes/admin/ajax.php +208 -208
  38. includes/admin/api-auth.php +583 -575
  39. includes/admin/capabilities.php +88 -88
  40. includes/admin/common.php +795 -811
  41. includes/admin/index.php +3 -3
  42. includes/admin/licensing/autoupdate.php +93 -93
  43. includes/admin/licensing/license-actions.php +0 -547
  44. includes/admin/licensing/skin.php +115 -104
  45. includes/admin/licensing/updater.php +0 -383
  46. includes/admin/notice.php +235 -235
  47. includes/admin/pages/addons.php +183 -138
  48. includes/admin/pages/reports.php +65 -64
  49. includes/admin/pages/settings.php +124 -123
  50. includes/admin/pages/tools.php +44 -44
  51. includes/admin/reporting.php +67 -67
  52. includes/admin/reports/abstract-report.php +439 -437
  53. includes/admin/reports/index.php +3 -3
  54. includes/admin/reports/overview.php +80 -80
  55. includes/admin/review.php +188 -163
  56. includes/admin/routes.php +677 -657
  57. includes/admin/tracking.php +246 -246
  58. includes/api-request.php +438 -438
  59. includes/auth.php +250 -243
  60. includes/deprecated.php +236 -236
  61. includes/frontend/class-tracking-abstract.php +78 -78
  62. includes/frontend/events/class-analytics-events.php +115 -115
  63. includes/frontend/events/index.php +3 -3
  64. includes/frontend/frontend.php +193 -185
  65. includes/frontend/index.php +3 -3
  66. includes/frontend/seedprod.php +44 -44
  67. includes/frontend/tracking/class-tracking-analytics.php +336 -336
  68. includes/frontend/tracking/class-tracking-preview.php +80 -80
  69. includes/frontend/tracking/index.php +3 -3
  70. includes/helpers.php +1242 -1179
  71. includes/index.php +3 -3
  72. includes/install.php +590 -544
  73. includes/license.php +0 -400
  74. includes/measurement-protocol.php +141 -141
  75. includes/options.php +414 -411
  76. index.php +3 -3
  77. languages/google-analytics-for-wordpress.pot +812 -622
README.md CHANGED
@@ -1,163 +1,163 @@
1
- # [MonsterInsights](https://www.monsterinsights.com) #
2
- The best Google Analytics Integration for WordPress. Period.<br />
3
- ![Plugin Version](https://img.shields.io/wordpress/plugin/v/google-analytics-for-wordpress.svg?maxAge=2592000)
4
- ![Total Downloads](https://img.shields.io/wordpress/plugin/dt/google-analytics-for-wordpress.svg?maxAge=2592000)
5
- ![WordPress Compatibility](https://img.shields.io/wordpress/v/google-analytics-for-wordpress.svg?maxAge=2592000)
6
- [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.2-8892BF.svg?style=flat-square)](https://php.net/)
7
- [![License](https://img.shields.io/badge/license-GPL--2.0%2B-red.svg)](https://github.com/awesomemotive/google-analytics-for-wordpress/blob/master/license.txt)
8
- [![Build Status](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/badges/build.png?b=master)](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/build-status/master)
9
- [![Code Intelligence Status](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/badges/code-intelligence.svg?b=master)](https://scrutinizer-ci.com/code-intelligence)
10
- [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/?branch=master)
11
- [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2944b6d77fa342f59764e79285da02bf)](https://www.codacy.com/app/chriscct7/google-analytics-for-wordpress?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=awesomemotive/google-analytics-for-wordpress&amp;utm_campaign=Badge_Grade)
12
-
13
- ## Contributions ##
14
- Anyone is welcome to contribute to MonsterInsights. Please read the [guidelines for contributing](https://github.com/awesomemotive/google-analytics-for-wordpress/blob/master/CONTRIBUTING.md) to this repository.
15
-
16
- There are various ways you can contribute:
17
-
18
- 1. Raise an [Issue](https://github.com/awesomemotive/google-analytics-for-wordpress/issues) on GitHub
19
- 2. Send us a Pull Request with your bug fixes and/or new features
20
- 3. Provide feedback and suggestions on [enhancements](https://github.com/awesomemotive/google-analytics-for-wordpress/issues?direction=desc&labels=Enhancement&page=1&sort=created&state=open)
21
-
22
- ## Bugs ##
23
- If you find an issue, let us know [here](https://github.com/awesomemotive/google-analytics-for-wordpress/issues?state=open)!
24
-
25
- ## Support ##
26
- This is a developer's portal for Google Analytics for WordPress by MonsterInsights and should not be used for support.
27
-
28
- For the lite version please use monsterinsights.com [Lite support](https://www.monsterinsights.com/lite-support/).
29
-
30
- For users of the pro version, please use the support form, located on the Support tab of the My Account page of our website (note: you must be logged in & have
31
- an active license to use this form).
32
-
33
- Please report security issues to support@monsterinsights.com
34
-
35
- ## Backwards Compatibility Guidelines for Developers ##
36
- Note all functionality on the admin side of the plugin, including any php/js/css functions, class names, files (or filenames), hooks or otherwise will not be garunteed backwards compatibility as a general rule. Our admin code is subject to change at any time without warning. As MonsterInsights is a frontend focused plugin, we're not too sure why you'd be building stuff with our backend code anyways. If you for some reason do need to use our backend code (anything located in admin or enqueued only in admin), please contact us with your usecase so we can adjust this policy and ensure your code will not break in the future.
37
-
38
- For the frontend, we will not garuntee that the JS output will always be the same, nor can we, as we will adjust it over time to ensure continued Google Analytics compatibility and add features. However, we will garuntee the backwards compatibility of any hooks (filters or actions) found exclusively in the `lite/includes/frontend`, `pro/includes/frontend`, and `includes/frontend` directories to the best of our abilities. These hooks are documented as such. Any sort of future breakage will be announced well in advance of any changes, and we'll try to never break anyone's use of these hooks.
39
-
40
- ## Code Styling Documentation ##
41
-
42
- MonsterInsights adheres to the WordPress core PHP standard with a couple deviations noted below. See https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/ for information on documenting using this standard.
43
-
44
- ### Deviations ###
45
-
46
- - [Use `elseif`, not `else if`](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#use-elseif-not-else-if)
47
- - In MonsterInsights, use `else if` as we do not permit use of the colon form of `if else`, rendering Core's reason for this rule null. Colon forms of `if else` are harder for text editors such as Sublime Text to parse the opening and closing of conditional logic, and thus are not permitted.
48
- - Avoid regular expressions wherever possible
49
- - Regular expressions make it more difficult for new contributors to contribute. Thus whenever possible, regular expressions should be avoided.
50
- - [Yoda Conditions](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#yoda-conditions)
51
- - Code should never be written where a variable is being non-strictly compared to `true` or `false`. Use the appropriate way of writing the if statement. `if ( true == $var )` is equivolent to `if ( $var )` and the latter is much easier to read. However when strict comparison is required (`===`), one should use `if ( true === $var )`.
52
-
53
- ### Additions ###
54
-
55
- - Required: Code should be formatted using tabs, set to size of 4 spaces
56
- - 4 spaces per tab is the universally accepted default tab size. Tabs are easier to read through in most editors. Additionally, they take up less file space than 4 spaces.
57
- - Required: Filter and function names should use underscores, not dashes
58
- - For consistency, all filter and functions should use underscores not dashes or CamelCasing when seperating words. Additionally, all filter and (functions not in a class) names should be preceeded by `monsterinsights_`. The only exception to this is filters that need to be pro or lite only, in which case they should be proceeded by `monsterinsights_pro_` and `monsterinsights_lite_` respectively. Functions in a class should not be preceeded by `monsterinsights_`.
59
- - Required: Hooks tied to a function not within a class, will be tied to the function after the end of the function's declaration
60
- - Since MonsterInsights requires all functions have a function docbloc immediately preceeding the declaration of a function, to make it easier to locate hooks tied to a function, the `add_action` or `add_filter` call(s) to a function shall be placed immediately after the end of a function declaration. For functions in classes, this rule does not apply as it is impossible to do this.
61
- - Recommended: Use pre-increments (`++i`) instead of post-increments (`i++`)
62
- - The former is more performant as it does not require a copy of the variable to be made. This rule is not strictly enforced, and where it detracts from the readability or simplicity of code, it should be ignored.
63
- - Recommended: Where possible avoid stored data changes
64
- - This plugin has a lot of active installs. As such, whereever possible, we should try to avoid requiring an upgrade routine to convert stored data. Having a routine that adds data to make something more performant is fine as long as it either falls back to existing data, a smart default, or stops execution (in a controlled manner).
65
-
66
- ## Language Translations, Textdomains, and Internationalization ##
67
-
68
- MonsterInsights is translation ready. Thanks to an extensive team of .org translators, much of the plugin is available translated into a wide variety of languages.
69
-
70
- ### What Textdomain to Use ##
71
-
72
- In googleanalytics-premium.php and in the /pro/ folder only use `ga-premium`. Everywhere else use `google-analytics-for-wordpress`.
73
-
74
- MonsterInsights Lite uses WordPress.org provided translation files. MonsterInsights Pro loads the Lite translation files for files shared with Lite, and also loads Pro-only translation files for the Pro-only files. These files are created automatically from Pro translations. The latest copy of these files are pulled down and deployed with each Pro release.
75
-
76
- ### How To Contribute Translations ###
77
-
78
- Via the WordPress.org translation system located [here](https://www.wordpress.org/plugins/google-analytics-for-wordpress/translations/).
79
-
80
- ### I've found a non-translatable string that a user can see. What should I do? ###
81
-
82
- Please open a [issue](https://github.com/awesomemotive/google-analytics-for-wordpress/issues) for it.
83
-
84
- ## Automation and External Libraries ##
85
-
86
- A project goal of MonsterInsights, is to embrace automation whenever possible.
87
-
88
- The MonsterInsights project taskrunner standard is Robo, and tasks for this project can be found in RoboFile.php (not available to public), and executed via:
89
- robo {command}
90
-
91
- The entire deployment process, the thing that makes a new MonsterInsights version and releases it, is completely automated (no human interaction required) via Robo.
92
-
93
- The MonsterInsights project dependency management system is Composer. Please make sure you don't accidentily override our composer file in your PRs.
94
-
95
- We also use Node/NPM to manage packages used by our plugin primarily for admin styling and functionality.
96
-
97
- We generally will always use the latest stable version of any Composer or NPM dependency, pulled and packaged during our automated release process, when possible. Some reasons we might use an out of date package include (but are not limited to):
98
-
99
- - Lack of PHP version support
100
- - A bug in the current version of the dependency that affects our plugin's use of the dependency
101
- - Lack of time to test the current version of the dependency before the release of our plugin
102
- - A security issue, which may or may not be public
103
- - A compatibility issue between a dependency and a different dependency
104
- - A change in the dependency that affects MonsterInsights's ability to be conflict-free with other plugins
105
- - and so forth
106
-
107
- When possible, we will always override/prefix all CSS rules, JS functions, and PHP class and function names in the dependencies we include when possible. With ~2 million active installs, not doing so is not an option (too many badly coded plugins out there). This process is completely automated, and done on release, between the step when composer/npm brings down the latest dependency versions, and when the zip files are autogenerated.
108
-
109
- When possible, we will also minify all JS/CSS files from dependencies into a single file that gets used, except when there's compatibility issues, or if there's a bug in the parser of the CSS/JS minifier we use.
110
-
111
- ## Warning About Package Managing MonsterInsights ##
112
-
113
- We do not maintain, nor have any current plans, to allow our plugin to be installed via Composer, Packagist, or other similar systems.
114
-
115
- We also do not recommend you via direct code or a management system (such as via a GitHub repo download Composer package), assume our plugin, on any branch, will be the current and/or stable branch of our plugin.
116
-
117
- The only official and maintained source of our plugin is on WordPress.org for the Lite version, and from the My Account area (or via the automatic updates) for the Pro version.
118
-
119
- ## Development Checkout Procedure ##
120
-
121
- `composer install`
122
- `cd assets`
123
- `npm update`
124
-
125
- ## Constants ##
126
-
127
- The following constants can be defined in a wp-config file to allow for sections of MonsterInsights to be turned on and off across an installation base (and also for unit testing)
128
-
129
- ### Both Pro & Lite ###
130
-
131
- Plugin defined:
132
- - `MONSTERINSIGHTS_VERSION`
133
- - The version of pro/lite installed
134
- - `MONSTERINSIGHTS_PLUGIN_NAME`
135
- - The name of the plugin
136
- - `MONSTERINSIGHTS_PLUGIN_SLUG`
137
- - The slug of this plugin
138
- - `MONSTERINSIGHTS_PLUGIN_FILE`
139
- - The name of this file
140
- - `MONSTERINSIGHTS_PLUGIN_DIR`
141
- - Path to the MI base folder
142
- - `MONSTERINSIGHTS_PLUGIN_URL`
143
- - URL to the MI base folder
144
-
145
- User defined:
146
- - `MONSTERINSIGHTS_LICENSE_KEY`
147
- - MonsterInsights license key to use as the fallback (please use auth though not this, as you can do this on the network panel now on multisites)
148
- - `MONSTERINSIGHTS_FORCE_ACTIVATION`
149
- - Override the WP version activation check. Use at your own risk.
150
- - `MONSTERINSIGHTS_AIRPLANE_MODE`
151
- - For future use. Currently does nothing. Useful for local site testing.
152
- - `MONSTERINSIGHTS_GA_UA`
153
- - Don't use oAuth or the wizard, but hardcode to use UA. Note, this will not allow backend reports to work. You can also use the filter `monsterinsights_get_ua`.
154
- - `MONSTERINSIGHTS_MULTISITE_GA_UA`.
155
- - You can use this constant to force the same the same UA for all subsites of an MS install. Note, this will not allow backend reports to work.
156
-
157
- ### Lite Only ###
158
- - `MONSTERINSIGHTS_LITE_VERSION`
159
- - The version of lite installed
160
-
161
- ### Pro Only ###
162
- - `MONSTERINSIGHTS_PRO_VERSION`
163
  - The version of pro installed
1
+ # [MonsterInsights](https://www.monsterinsights.com) #
2
+ The best Google Analytics Integration for WordPress. Period.<br />
3
+ ![Plugin Version](https://img.shields.io/wordpress/plugin/v/google-analytics-for-wordpress.svg?maxAge=2592000)
4
+ ![Total Downloads](https://img.shields.io/wordpress/plugin/dt/google-analytics-for-wordpress.svg?maxAge=2592000)
5
+ ![WordPress Compatibility](https://img.shields.io/wordpress/v/google-analytics-for-wordpress.svg?maxAge=2592000)
6
+ [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.2-8892BF.svg?style=flat-square)](https://php.net/)
7
+ [![License](https://img.shields.io/badge/license-GPL--2.0%2B-red.svg)](https://github.com/awesomemotive/google-analytics-for-wordpress/blob/master/license.txt)
8
+ [![Build Status](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/badges/build.png?b=master)](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/build-status/master)
9
+ [![Code Intelligence Status](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/badges/code-intelligence.svg?b=master)](https://scrutinizer-ci.com/code-intelligence)
10
+ [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/awesomemotive/google-analytics-for-wordpress/?branch=master)
11
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2944b6d77fa342f59764e79285da02bf)](https://www.codacy.com/app/chriscct7/google-analytics-for-wordpress?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=awesomemotive/google-analytics-for-wordpress&amp;utm_campaign=Badge_Grade)
12
+
13
+ ## Contributions ##
14
+ Anyone is welcome to contribute to MonsterInsights. Please read the [guidelines for contributing](https://github.com/awesomemotive/google-analytics-for-wordpress/blob/master/CONTRIBUTING.md) to this repository.
15
+
16
+ There are various ways you can contribute:
17
+
18
+ 1. Raise an [Issue](https://github.com/awesomemotive/google-analytics-for-wordpress/issues) on GitHub
19
+ 2. Send us a Pull Request with your bug fixes and/or new features
20
+ 3. Provide feedback and suggestions on [enhancements](https://github.com/awesomemotive/google-analytics-for-wordpress/issues?direction=desc&labels=Enhancement&page=1&sort=created&state=open)
21
+
22
+ ## Bugs ##
23
+ If you find an issue, let us know [here](https://github.com/awesomemotive/google-analytics-for-wordpress/issues?state=open)!
24
+
25
+ ## Support ##
26
+ This is a developer's portal for Google Analytics for WordPress by MonsterInsights and should not be used for support.
27
+
28
+ For the lite version please use monsterinsights.com [Lite support](https://www.monsterinsights.com/lite-support/).
29
+
30
+ For users of the pro version, please use the support form, located on the Support tab of the My Account page of our website (note: you must be logged in & have
31
+ an active license to use this form).
32
+
33
+ Please report security issues to support@monsterinsights.com
34
+
35
+ ## Backwards Compatibility Guidelines for Developers ##
36
+ Note all functionality on the admin side of the plugin, including any php/js/css functions, class names, files (or filenames), hooks or otherwise will not be garunteed backwards compatibility as a general rule. Our admin code is subject to change at any time without warning. As MonsterInsights is a frontend focused plugin, we're not too sure why you'd be building stuff with our backend code anyways. If you for some reason do need to use our backend code (anything located in admin or enqueued only in admin), please contact us with your usecase so we can adjust this policy and ensure your code will not break in the future.
37
+
38
+ For the frontend, we will not garuntee that the JS output will always be the same, nor can we, as we will adjust it over time to ensure continued Google Analytics compatibility and add features. However, we will garuntee the backwards compatibility of any hooks (filters or actions) found exclusively in the `lite/includes/frontend`, `pro/includes/frontend`, and `includes/frontend` directories to the best of our abilities. These hooks are documented as such. Any sort of future breakage will be announced well in advance of any changes, and we'll try to never break anyone's use of these hooks.
39
+
40
+ ## Code Styling Documentation ##
41
+
42
+ MonsterInsights adheres to the WordPress core PHP standard with a couple deviations noted below. See https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/ for information on documenting using this standard.
43
+
44
+ ### Deviations ###
45
+
46
+ - [Use `elseif`, not `else if`](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#use-elseif-not-else-if)
47
+ - In MonsterInsights, use `else if` as we do not permit use of the colon form of `if else`, rendering Core's reason for this rule null. Colon forms of `if else` are harder for text editors such as Sublime Text to parse the opening and closing of conditional logic, and thus are not permitted.
48
+ - Avoid regular expressions wherever possible
49
+ - Regular expressions make it more difficult for new contributors to contribute. Thus whenever possible, regular expressions should be avoided.
50
+ - [Yoda Conditions](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#yoda-conditions)
51
+ - Code should never be written where a variable is being non-strictly compared to `true` or `false`. Use the appropriate way of writing the if statement. `if ( true == $var )` is equivolent to `if ( $var )` and the latter is much easier to read. However when strict comparison is required (`===`), one should use `if ( true === $var )`.
52
+
53
+ ### Additions ###
54
+
55
+ - Required: Code should be formatted using tabs, set to size of 4 spaces
56
+ - 4 spaces per tab is the universally accepted default tab size. Tabs are easier to read through in most editors. Additionally, they take up less file space than 4 spaces.
57
+ - Required: Filter and function names should use underscores, not dashes
58
+ - For consistency, all filter and functions should use underscores not dashes or CamelCasing when seperating words. Additionally, all filter and (functions not in a class) names should be preceeded by `monsterinsights_`. The only exception to this is filters that need to be pro or lite only, in which case they should be proceeded by `monsterinsights_pro_` and `monsterinsights_lite_` respectively. Functions in a class should not be preceeded by `monsterinsights_`.
59
+ - Required: Hooks tied to a function not within a class, will be tied to the function after the end of the function's declaration
60
+ - Since MonsterInsights requires all functions have a function docbloc immediately preceeding the declaration of a function, to make it easier to locate hooks tied to a function, the `add_action` or `add_filter` call(s) to a function shall be placed immediately after the end of a function declaration. For functions in classes, this rule does not apply as it is impossible to do this.
61
+ - Recommended: Use pre-increments (`++i`) instead of post-increments (`i++`)
62
+ - The former is more performant as it does not require a copy of the variable to be made. This rule is not strictly enforced, and where it detracts from the readability or simplicity of code, it should be ignored.
63
+ - Recommended: Where possible avoid stored data changes
64
+ - This plugin has a lot of active installs. As such, whereever possible, we should try to avoid requiring an upgrade routine to convert stored data. Having a routine that adds data to make something more performant is fine as long as it either falls back to existing data, a smart default, or stops execution (in a controlled manner).
65
+
66
+ ## Language Translations, Textdomains, and Internationalization ##
67
+
68
+ MonsterInsights is translation ready. Thanks to an extensive team of .org translators, much of the plugin is available translated into a wide variety of languages.
69
+
70
+ ### What Textdomain to Use ##
71
+
72
+ In googleanalytics-premium.php and in the /pro/ folder only use `ga-premium`. Everywhere else use `google-analytics-for-wordpress`.
73
+
74
+ MonsterInsights Lite uses WordPress.org provided translation files. MonsterInsights Pro loads the Lite translation files for files shared with Lite, and also loads Pro-only translation files for the Pro-only files. These files are created automatically from Pro translations. The latest copy of these files are pulled down and deployed with each Pro release.
75
+
76
+ ### How To Contribute Translations ###
77
+
78
+ Via the WordPress.org translation system located [here](https://www.wordpress.org/plugins/google-analytics-for-wordpress/translations/).
79
+
80
+ ### I've found a non-translatable string that a user can see. What should I do? ###
81
+
82
+ Please open a [issue](https://github.com/awesomemotive/google-analytics-for-wordpress/issues) for it.
83
+
84
+ ## Automation and External Libraries ##
85
+
86
+ A project goal of MonsterInsights, is to embrace automation whenever possible.
87
+
88
+ The MonsterInsights project taskrunner standard is Robo, and tasks for this project can be found in RoboFile.php (not available to public), and executed via:
89
+ robo {command}
90
+
91
+ The entire deployment process, the thing that makes a new MonsterInsights version and releases it, is completely automated (no human interaction required) via Robo.
92
+
93
+ The MonsterInsights project dependency management system is Composer. Please make sure you don't accidentily override our composer file in your PRs.
94
+
95
+ We also use Node/NPM to manage packages used by our plugin primarily for admin styling and functionality.
96
+
97
+ We generally will always use the latest stable version of any Composer or NPM dependency, pulled and packaged during our automated release process, when possible. Some reasons we might use an out of date package include (but are not limited to):
98
+
99
+ - Lack of PHP version support
100
+ - A bug in the current version of the dependency that affects our plugin's use of the dependency
101
+ - Lack of time to test the current version of the dependency before the release of our plugin
102
+ - A security issue, which may or may not be public
103
+ - A compatibility issue between a dependency and a different dependency
104
+ - A change in the dependency that affects MonsterInsights's ability to be conflict-free with other plugins
105
+ - and so forth
106
+
107
+ When possible, we will always override/prefix all CSS rules, JS functions, and PHP class and function names in the dependencies we include when possible. With ~2 million active installs, not doing so is not an option (too many badly coded plugins out there). This process is completely automated, and done on release, between the step when composer/npm brings down the latest dependency versions, and when the zip files are autogenerated.
108
+
109
+ When possible, we will also minify all JS/CSS files from dependencies into a single file that gets used, except when there's compatibility issues, or if there's a bug in the parser of the CSS/JS minifier we use.
110
+
111
+ ## Warning About Package Managing MonsterInsights ##
112
+
113
+ We do not maintain, nor have any current plans, to allow our plugin to be installed via Composer, Packagist, or other similar systems.
114
+
115
+ We also do not recommend you via direct code or a management system (such as via a GitHub repo download Composer package), assume our plugin, on any branch, will be the current and/or stable branch of our plugin.
116
+
117
+ The only official and maintained source of our plugin is on WordPress.org for the Lite version, and from the My Account area (or via the automatic updates) for the Pro version.
118
+
119
+ ## Development Checkout Procedure ##
120
+
121
+ `composer install`
122
+ `cd assets`
123
+ `npm update`
124
+
125
+ ## Constants ##
126
+
127
+ The following constants can be defined in a wp-config file to allow for sections of MonsterInsights to be turned on and off across an installation base (and also for unit testing)
128
+
129
+ ### Both Pro & Lite ###
130
+
131
+ Plugin defined:
132
+ - `MONSTERINSIGHTS_VERSION`
133
+ - The version of pro/lite installed
134
+ - `MONSTERINSIGHTS_PLUGIN_NAME`
135
+ - The name of the plugin
136
+ - `MONSTERINSIGHTS_PLUGIN_SLUG`
137
+ - The slug of this plugin
138
+ - `MONSTERINSIGHTS_PLUGIN_FILE`
139
+ - The name of this file
140
+ - `MONSTERINSIGHTS_PLUGIN_DIR`
141
+ - Path to the MI base folder
142
+ - `MONSTERINSIGHTS_PLUGIN_URL`
143
+ - URL to the MI base folder
144
+
145
+ User defined:
146
+ - `MONSTERINSIGHTS_LICENSE_KEY`
147
+ - MonsterInsights license key to use as the fallback (please use auth though not this, as you can do this on the network panel now on multisites)
148
+ - `MONSTERINSIGHTS_FORCE_ACTIVATION`
149
+ - Override the WP version activation check. Use at your own risk.
150
+ - `MONSTERINSIGHTS_AIRPLANE_MODE`
151
+ - For future use. Currently does nothing. Useful for local site testing.
152
+ - `MONSTERINSIGHTS_GA_UA`
153
+ - Don't use oAuth or the wizard, but hardcode to use UA. Note, this will not allow backend reports to work. You can also use the filter `monsterinsights_get_ua`.
154
+ - `MONSTERINSIGHTS_MULTISITE_GA_UA`.
155
+ - You can use this constant to force the same the same UA for all subsites of an MS install. Note, this will not allow backend reports to work.
156
+
157
+ ### Lite Only ###
158
+ - `MONSTERINSIGHTS_LITE_VERSION`
159
+ - The version of lite installed
160
+
161
+ ### Pro Only ###
162
+ - `MONSTERINSIGHTS_PRO_VERSION`
163
  - The version of pro installed
assets/css/admin-common.css CHANGED
@@ -1,56 +1,56 @@
1
- #toplevel_page_monsterinsights_reports .wp-menu-image img,
2
- #toplevel_page_monsterinsights_settings .wp-menu-image img,
3
- #toplevel_page_monsterinsights_network .wp-menu-image img {
4
- width: 18px;
5
- height: 18px;
6
- padding-top: 7px;
7
- }
8
-
9
- .monsterinsights-wooedd-upsell-left {
10
- width: 50%;
11
- display: table-cell;
12
- float: left;
13
- }
14
-
15
- .monsterinsights-wooedd-upsell-right {
16
- width: 50%;
17
- display: table-cell;
18
- float: left;
19
- }
20
-
21
- .monsterinsights-wooedd-upsell-image {
22
- width: 100%;
23
- height: auto;
24
- padding: 20px;
25
- }
26
-
27
- .monsterinsights-wooedd-upsell-image-small {
28
- display: none;
29
- }
30
-
31
- .monsterinsights-wooedd-upsell-row {
32
- display: table;
33
- }
34
-
35
- .monsterinsights-wooedd-upsell-left p {
36
- margin: 1em 0;
37
- font-size: 16px;
38
- }
39
-
40
- @media (max-width: 900px) {
41
- .monsterinsights-wooedd-upsell-left {
42
- width: 100%;
43
- }
44
-
45
- .monsterinsights-wooedd-upsell-right {
46
- display: none;
47
- }
48
-
49
- .monsterinsights-wooedd-upsell-image-small {
50
- display: block;
51
- }
52
-
53
- .monsterinsights-wooedd-upsell-image-large {
54
- display: none;
55
- }
56
- }
1
+ #toplevel_page_monsterinsights_reports .wp-menu-image img,
2
+ #toplevel_page_monsterinsights_settings .wp-menu-image img,
3
+ #toplevel_page_monsterinsights_network .wp-menu-image img {
4
+ width: 18px;
5
+ height: auto;
6
+ padding-top: 7px;
7
+ }
8
+
9
+ .monsterinsights-wooedd-upsell-left {
10
+ width: 50%;
11
+ display: table-cell;
12
+ float: left;
13
+ }
14
+
15
+ .monsterinsights-wooedd-upsell-right {
16
+ width: 50%;
17
+ display: table-cell;
18
+ float: left;
19
+ }
20
+
21
+ .monsterinsights-wooedd-upsell-image {
22
+ width: 100%;
23
+ height: auto;
24
+ padding: 20px;
25
+ }
26
+
27
+ .monsterinsights-wooedd-upsell-image-small {
28
+ display: none;
29
+ }
30
+
31
+ .monsterinsights-wooedd-upsell-row {
32
+ display: table;
33
+ }
34
+
35
+ .monsterinsights-wooedd-upsell-left p {
36
+ margin: 1em 0;
37
+ font-size: 16px;
38
+ }
39
+
40
+ @media (max-width: 900px) {
41
+ .monsterinsights-wooedd-upsell-left {
42
+ width: 100%;
43
+ }
44
+
45
+ .monsterinsights-wooedd-upsell-right {
46
+ display: none;
47
+ }
48
+
49
+ .monsterinsights-wooedd-upsell-image-small {
50
+ display: block;
51
+ }
52
+
53
+ .monsterinsights-wooedd-upsell-image-large {
54
+ display: none;
55
+ }
56
+ }
assets/css/admin-common.min.css CHANGED
@@ -1 +1 @@
1
- #toplevel_page_monsterinsights_reports .wp-menu-image img,#toplevel_page_monsterinsights_settings .wp-menu-image img,#toplevel_page_monsterinsights_network .wp-menu-image img{width:18px;height:18px;padding-top:7px}.monsterinsights-wooedd-upsell-left{width:50%;display:table-cell;float:left}.monsterinsights-wooedd-upsell-right{width:50%;display:table-cell;float:left}.monsterinsights-wooedd-upsell-image{width:100%;height:auto;padding:20px}.monsterinsights-wooedd-upsell-image-small{display:none}.monsterinsights-wooedd-upsell-row{display:table}.monsterinsights-wooedd-upsell-left p{margin:1em 0;font-size:16px}@media (max-width: 900px){.monsterinsights-wooedd-upsell-left{width:100%}.monsterinsights-wooedd-upsell-right{display:none}.monsterinsights-wooedd-upsell-image-small{display:block}.monsterinsights-wooedd-upsell-image-large{display:none}}
1
+ #toplevel_page_monsterinsights_reports .wp-menu-image img,#toplevel_page_monsterinsights_settings .wp-menu-image img,#toplevel_page_monsterinsights_network .wp-menu-image img{width:18px;height:auto;padding-top:7px}.monsterinsights-wooedd-upsell-left{width:50%;display:table-cell;float:left}.monsterinsights-wooedd-upsell-right{width:50%;display:table-cell;float:left}.monsterinsights-wooedd-upsell-image{width:100%;height:auto;padding:20px}.monsterinsights-wooedd-upsell-image-small{display:none}.monsterinsights-wooedd-upsell-row{display:table}.monsterinsights-wooedd-upsell-left p{margin:1em 0;font-size:16px}@media (max-width: 900px){.monsterinsights-wooedd-upsell-left{width:100%}.monsterinsights-wooedd-upsell-right{display:none}.monsterinsights-wooedd-upsell-image-small{display:block}.monsterinsights-wooedd-upsell-image-large{display:none}}
assets/css/images/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/css/images/logo.png CHANGED
Binary file
assets/css/images/logo@2x.png CHANGED
Binary file
assets/css/images/mascot.png CHANGED
Binary file
assets/css/images/mascot@2x.png CHANGED
Binary file
assets/css/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/fonts/README.md CHANGED
@@ -1,17 +1,17 @@
1
- # Updating Icons
2
-
3
- The main font used by MonsterInsights for icons has the font-family: 'Misettings'.
4
-
5
- The files used by this font are
6
-
7
- - assets/fonts/icons.eot
8
- - assets/fonts/icons.otf
9
- - assets/fonts/icons.ttf
10
- - assets/fonts/icons.woff
11
- - assets/fonts/icons.woff2
12
-
13
- The font files are generated using [FortAwesome](https://fortawesome.com).
14
-
15
- After generating new files, you'll need to update the files mentioned above & the css
16
- used for the icons which can be found in assets/css/admin.css starting on line 135, look
17
- for the class `.monstericon-`.
1
+ # Updating Icons
2
+
3
+ The main font used by MonsterInsights for icons has the font-family: 'Misettings'.
4
+
5
+ The files used by this font are
6
+
7
+ - assets/fonts/icons.eot
8
+ - assets/fonts/icons.otf
9
+ - assets/fonts/icons.ttf
10
+ - assets/fonts/icons.woff
11
+ - assets/fonts/icons.woff2
12
+
13
+ The font files are generated using [FortAwesome](https://fortawesome.com).
14
+
15
+ After generating new files, you'll need to update the files mentioned above & the css
16
+ used for the icons which can be found in assets/css/admin.css starting on line 135, look
17
+ for the class `.monstericon-`.
assets/fonts/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/images/chart.png DELETED
Binary file
assets/images/down-green.png CHANGED
Binary file
assets/images/down-green@2x.png CHANGED
Binary file
assets/images/down.png CHANGED
Binary file
assets/images/down@2x.png CHANGED
Binary file
assets/images/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/images/plugin-om.png CHANGED
Binary file
assets/images/plugin-smtp.png CHANGED
Binary file
assets/images/plugin-wpforms.png CHANGED
Binary file
assets/images/question-mark.png CHANGED
Binary file
assets/images/up-red.png CHANGED
Binary file
assets/images/up-red@2x.png CHANGED
Binary file
assets/images/up.png CHANGED
Binary file
assets/images/up@2x.png CHANGED
Binary file
assets/images/woo-edd-upsell.png DELETED
Binary file
assets/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/js/admin-common.js CHANGED
@@ -1,25 +1,25 @@
1
- jQuery( document ).ready( function( $ ) {
2
- /**
3
- * Dismissable Notices
4
- * - Sends an AJAX request to mark the notice as dismissed
5
- */
6
- $( 'div.monsterinsights-notice' ).on( 'click', 'button.notice-dismiss', function( e ) {
7
- e.preventDefault();
8
- $( this ).closest( 'div.monsterinsights-notice' ).fadeOut();
9
-
10
- // If this is a dismissible notice, it means we need to send an AJAX request
11
- if ( $( this ).parent().hasClass( 'is-dismissible' ) ) {
12
- $.post(
13
- monsterinsights_admin_common.ajax,
14
- {
15
- action: 'monsterinsights_ajax_dismiss_notice',
16
- nonce: monsterinsights_admin_common.dismiss_notice_nonce,
17
- notice: $( this ).parent().data( 'notice' )
18
- },
19
- function( response ) {},
20
- 'json'
21
- );
22
- }
23
-
24
- } );
25
  });
1
+ jQuery( document ).ready( function( $ ) {
2
+ /**
3
+ * Dismissable Notices
4
+ * - Sends an AJAX request to mark the notice as dismissed
5
+ */
6
+ $( 'div.monsterinsights-notice' ).on( 'click', 'button.notice-dismiss', function( e ) {
7
+ e.preventDefault();
8
+ $( this ).closest( 'div.monsterinsights-notice' ).fadeOut();
9
+
10
+ // If this is a dismissible notice, it means we need to send an AJAX request
11
+ if ( $( this ).parent().hasClass( 'is-dismissible' ) ) {
12
+ $.post(
13
+ monsterinsights_admin_common.ajax,
14
+ {
15
+ action: 'monsterinsights_ajax_dismiss_notice',
16
+ nonce: monsterinsights_admin_common.dismiss_notice_nonce,
17
+ notice: $( this ).parent().data( 'notice' )
18
+ },
19
+ function( response ) {},
20
+ 'json'
21
+ );
22
+ }
23
+
24
+ } );
25
  });
assets/js/frontend.js CHANGED
@@ -1,600 +1,600 @@
1
- /**
2
- * Developer's Notice:
3
- *
4
- * Note: JS in this file (and this file itself) is not garunteed backwards compatibility. JS can be added, changed or removed at any time without notice.
5
- * For more information see the `Backwards Compatibility Guidelines for Developers` section of the README.md file.
6
- */
7
- /**
8
- * Handles:
9
- * - JS Events handling
10
- *
11
- * @since 6.0.12
12
- */
13
- var MonsterInsights = function(){
14
- /* MonsterInsights JS events tracking works on all major browsers, including IE starting at IE 7, via polyfills for any major JS function used that
15
- is not supported by at least 95% of the global and/or US browser marketshare. Currently, IE 7 & 8 which as of 2/14/17 have under 0.25% global marketshare, require
16
- us to polyfill Array.prototype.lastIndexOf, and if they continue to drop, we might remove this polyfill at some point. In that case note that events tracking
17
- for IE 7/8 will continue to work, with the exception of events tracking of downloads. */
18
- var lastClicked = [];
19
- var internalAsOutboundCategory = '';
20
-
21
- this.setLastClicked = function(valuesArray,fieldsArray,tracked){
22
- valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
23
- fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : [];
24
- tracked = typeof tracked !== 'undefined' ? tracked : false;
25
-
26
- lastClicked.valuesArray = valuesArray;
27
- lastClicked.fieldsArray = fieldsArray;
28
- };
29
-
30
- this.getLastClicked = function () {
31
- return lastClicked;
32
- };
33
-
34
- this.setInternalAsOutboundCategory = function( category ){
35
- internalAsOutboundCategory = category;
36
- };
37
-
38
- this.getInternalAsOutboundCategory = function () {
39
- return internalAsOutboundCategory;
40
- };
41
-
42
- this.sendEvent = function ( fieldsArray ) {
43
- __gaTrackerSend( [], fieldsArray );
44
- };
45
-
46
- function __gaTrackerIsDebug () {
47
- if ( window.monsterinsights_debug_mode ) {
48
- return true;
49
- } else {
50
- return false;
51
- }
52
- }
53
-
54
- function __gaTrackerSend ( valuesArray, fieldsArray ) {
55
- valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
56
- fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : {};
57
-
58
- __gaTracker( 'send', fieldsArray );
59
-
60
- lastClicked.valuesArray = valuesArray;
61
- lastClicked.fieldsArray = fieldsArray;
62
- lastClicked.tracked = true;
63
- __gaTrackerLog( 'Tracked: ' + valuesArray.type );
64
- __gaTrackerLog( lastClicked );
65
- }
66
-
67
- function __gaTrackerNotSend ( valuesArray ) {
68
- valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
69
-
70
- lastClicked.valuesArray = valuesArray;
71
- lastClicked.fieldsArray = [];
72
- lastClicked.tracked = false;
73
- __gaTrackerLog( 'Not Tracked: ' + valuesArray.exit );
74
- __gaTrackerLog( lastClicked );
75
- }
76
-
77
- function __gaTrackerLog ( message ) {
78
- if ( __gaTrackerIsDebug() ) {
79
- console.dir( message );
80
- }
81
- }
82
-
83
- function __gaTrackerStringTrim( x ) {
84
- return x.replace(/^\s+|\s+$/gm,'');
85
- }
86
-
87
- function __gaTrackerGetDomain() {
88
- var i=0,currentdomain=document.domain,p=currentdomain.split('.'),s='_gd'+(new Date()).getTime();
89
- while(i<(p.length-1) && document.cookie.indexOf(s+'='+s)==-1){
90
- currentdomain = p.slice(-1-(++i)).join('.');
91
- document.cookie = s+"="+s+";domain="+currentdomain+";";
92
- }
93
- document.cookie = s+"=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain="+currentdomain+";";
94
- return currentdomain;
95
- }
96
-
97
- function __gaTrackerGetExtension( extension ) {
98
- extension = extension.toString();
99
- extension = extension.substring( 0, (extension.indexOf( "#" ) == -1 ) ? extension.length : extension.indexOf( "#" ) ); /* Remove the anchor at the end, if there is one */
100
- extension = extension.substring( 0, (extension.indexOf( "?" ) == -1 ) ? extension.length : extension.indexOf( "?" ) ); /* Remove the query after the file name, if there is one */
101
- extension = extension.substring( extension.lastIndexOf( "/" ) + 1, extension.length ); /* Remove everything before the last slash in the path */
102
- if ( extension.length > 0 && extension.indexOf('.') !== -1 ) { /* If there's a period left in the URL, then there's a extension. Else it is not a extension. */
103
- extension = extension.substring( extension.indexOf( "." ) + 1 ); /* Remove everything but what's after the first period */
104
- return extension;
105
- } else {
106
- return "";
107
- }
108
- }
109
-
110
- function __gaTrackerLoaded() {
111
- return typeof(__gaTracker) !== 'undefined' && __gaTracker && __gaTracker.hasOwnProperty( "loaded" ) && __gaTracker.loaded == true; /* jshint ignore:line */
112
- }
113
-
114
- function __gaTrackerTrackedClick( event ) {
115
- return event.which == 1 || event.which == 2 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
116
- }
117
-
118
- function __gaTrackerGetDownloadExtensions() {
119
- var download_extensions = [];
120
- if ( typeof monsterinsights_frontend.download_extensions == 'string' ) {
121
- download_extensions = monsterinsights_frontend.download_extensions.split(",");
122
- }
123
- return download_extensions;
124
- }
125
-
126
- function __gaTrackerGetInboundPaths() {
127
- var inbound_paths = [];
128
- if ( typeof monsterinsights_frontend.inbound_paths == 'string' ) {
129
- inbound_paths = JSON.parse( monsterinsights_frontend.inbound_paths );
130
- }
131
-
132
- return inbound_paths;
133
- }
134
-
135
- function __gaTrackerTrackedClickType( event ) {
136
- if ( event.which == 1 ) {
137
- return 'event.which=1';
138
- } else if ( event.which == 2 ) {
139
- return 'event.which=2';
140
- } else if ( event.metaKey ){
141
- return 'metaKey';
142
- } else if ( event.ctrlKey ) {
143
- return 'ctrlKey';
144
- } else if ( event.shiftKey ) {
145
- return 'shiftKey';
146
- } else if ( event.altKey ) {
147
- return 'altKey';
148
- } else {
149
- return '';
150
- }
151
- }
152
-
153
- function __gaTrackerLinkType( el ) {
154
- var download_extensions = __gaTrackerGetDownloadExtensions();
155
- var inbound_paths = __gaTrackerGetInboundPaths();
156
- var type = 'unknown';
157
- var link = el.href;
158
- var extension = __gaTrackerGetExtension( el.href );
159
- var currentdomain = __gaTrackerGetDomain();
160
- var hostname = el.hostname;
161
- var protocol = el.protocol;
162
- var pathname = el.pathname;
163
- link = link.toString();
164
- var index, len;
165
- var category = el.getAttribute("data-vars-ga-category");
166
-
167
- if ( category ) {
168
- return category;
169
- }
170
-
171
- if ( link.match( /^javascript\:/i ) ) {
172
- type = 'internal'; /* if it's a JS link, it's internal */
173
- } else if ( protocol && protocol.length > 0 && ( __gaTrackerStringTrim( protocol ) == 'tel' || __gaTrackerStringTrim( protocol ) == 'tel:' ) ) { /* If it's a telephone link */
174
- type = "tel";
175
- } else if ( protocol && protocol.length > 0 && ( __gaTrackerStringTrim( protocol ) == 'mailto' || __gaTrackerStringTrim( protocol ) == 'mailto:' ) ) { /* If it's a email */
176
- type = "mailto";
177
- } else if ( hostname && currentdomain && hostname.length > 0 && currentdomain.length > 0 && ! hostname.endsWith( currentdomain ) ) { /* If it's a outbound */
178
- type = "external";
179
- } else if ( pathname && JSON.stringify( inbound_paths ) != "{}" && pathname.length > 0 ) { /* If it's an internal as outbound */
180
- var inbound_paths_length = inbound_paths.length;
181
- for ( var inbound_paths_index = 0; inbound_paths_index < inbound_paths_length; inbound_paths_index ++ ) {
182
- if ( inbound_paths[ inbound_paths_index ].path && inbound_paths[ inbound_paths_index ].label && inbound_paths[ inbound_paths_index ].path.length > 0 && inbound_paths[ inbound_paths_index ].label.length > 0 && pathname.startsWith( inbound_paths[ inbound_paths_index ].path ) ) {
183
- type = "internal-as-outbound";
184
- internalAsOutboundCategory = "outbound-link-" + inbound_paths[ inbound_paths_index ].label;
185
- break;
186
- }
187
- }
188
- /* Enable window.monsterinsights_experimental_mode at your own risk. We might eventually remove it. Also you may/can/will burn through GA quota for your property quickly. */
189
- } else if ( hostname && window.monsterinsights_experimental_mode && hostname.length > 0 && document.domain.length > 0 && hostname !== document.domain ) { /* If it's a cross-hostname link */
190
- type = "cross-hostname";
191
- }
192
-
193
- if ( extension && ( type === 'unknown' || 'external' === type ) && download_extensions.length > 0 && extension.length > 0 ) { /* If it's a download */
194
- for ( index = 0, len = download_extensions.length; index < len; ++index ) {
195
- if ( download_extensions[ index ].length > 0 && ( link.endsWith( download_extensions[ index ] ) || download_extensions[ index ] == extension ) ) {
196
- type = "download";
197
- break;
198
- }
199
- }
200
- }
201
-
202
- if ( type === 'unknown' ) {
203
- type = 'internal';
204
- }
205
- return type;
206
- }
207
-
208
- function __gaTrackerLinkTarget( el, event ) {
209
-
210
- /* Is actual target set and not _(self|parent|top)? */
211
- var target = ( el.target && !el.target.match( /^_(self|parent|top)$/i ) ) ? el.target : false;
212
-
213
- /* Assume a target if Ctrl|shift|meta-click */
214
- if ( event.ctrlKey || event.shiftKey || event.metaKey || event.which == 2 ) {
215
- target = "_blank";
216
- }
217
- return target;
218
- }
219
-
220
- function __gaTrackerClickEvent( event ) {
221
- var el = event.srcElement || event.target;
222
- var valuesArray = [];
223
- var fieldsArray;
224
-
225
- /* Start Values Array */
226
- valuesArray.el = el;
227
- valuesArray.ga_loaded = __gaTrackerLoaded();
228
- valuesArray.click_type = __gaTrackerTrackedClickType( event );
229
-
230
- /* If GA is blocked or not loaded, or not main|middle|touch click then don't track */
231
- if ( ! __gaTrackerLoaded() || ! __gaTrackerTrackedClick( event ) ) {
232
- valuesArray.exit = 'loaded';
233
- __gaTrackerNotSend( valuesArray );
234
- return;
235
- }
236
-
237
- /* Loop up the DOM tree through parent elements if clicked element is not a link (eg: an image inside a link) */
238
- while ( el && (typeof el.tagName == 'undefined' || el.tagName.toLowerCase() != 'a' || ! el.href ) ) {
239
- el = el.parentNode;
240
- }
241
-
242
- /* if a link with valid href has been clicked */
243
- if ( el && el.href && ! el.hasAttribute('xlink:href') ) {
244
- var link = el.href; /* What link are we tracking */
245
- var extension = __gaTrackerGetExtension( el.href ); /* What extension is this link */
246
- var download_extensions = __gaTrackerGetDownloadExtensions(); /* Let's get the extensions to track */
247
- var inbound_paths = __gaTrackerGetInboundPaths(); /* Let's get the internal paths to track */
248
- var home_url = monsterinsights_frontend.home_url; /* Let's get the url to compare for external/internal use */
249
- var currentdomain = __gaTrackerGetDomain(); /* What domain are we on? */
250
- var type = __gaTrackerLinkType( el ); /* What type of link is this? */
251
- var target = __gaTrackerLinkTarget( el, event ); /* Is a new tab/window being opened? */
252
- var action = el.getAttribute("data-vars-ga-action");
253
- var label = el.getAttribute("data-vars-ga-label");
254
-
255
- /* Element */
256
- valuesArray.el = el; /* el is an a element so we can parse it */
257
- valuesArray.el_href = el.href; /* "http://example.com:3000/pathname/?search=test#hash" */
258
- valuesArray.el_protocol = el.protocol; /* "http:" */
259
- valuesArray.el_hostname = el.hostname; /* "example.com" */
260
- valuesArray.el_port = el.port; /* "3000" */
261
- valuesArray.el_pathname = el.pathname; /* "/pathname/" */
262
- valuesArray.el_search = el.search; /* "?search=test" */
263
- valuesArray.el_hash = el.hash; /* "#hash" */
264
- valuesArray.el_host = el.host; /* "example.com:3000" */
265
-
266
- /* Settings */
267
- valuesArray.debug_mode = __gaTrackerIsDebug(); /* "example.com:3000" */
268
- valuesArray.download_extensions = download_extensions; /* Let's get the extensions to track */
269
- valuesArray.inbound_paths = inbound_paths; /* Let's get the internal paths to track */
270
- valuesArray.home_url = home_url; /* Let's get the url to compare for external/internal use */
271
-
272
- /* Parsed/Logic */
273
- valuesArray.link = link; /* What link are we tracking */
274
- valuesArray.extension = extension; /* What extension is this link */
275
- valuesArray.type = type; /* What type of link is this */
276
- valuesArray.target = target; /* Is a new tab/window being opened? */
277
- valuesArray.title = el.title || el.innerText || el.getAttribute('aria-label') || el.textContent; /* Try link title, then text content */
278
-
279
- /* Let's track everything but internals (that aren't internal-as-externals) and javascript */
280
- if ( type !== 'internal' && type !== 'javascript' ) {
281
-
282
- var __gaTrackerHitBackRun = false; /* Tracker has not yet run */
283
-
284
- /* HitCallback to open link in same window after tracker */
285
- var __gaTrackerHitBack = function() {
286
- /* Run the hitback only once */
287
- if ( __gaTrackerHitBackRun ){
288
- return;
289
- }
290
- __gaTrackerHitBackRun = true;
291
- window.location.href = link;
292
- };
293
-
294
- var __gaTrackerNoRedirectExternal = function() {
295
- valuesArray.exit = 'external';
296
- __gaTrackerNotSend( valuesArray );
297
- };
298
-
299
- var __gaTrackerNoRedirectInboundAsExternal = function() {
300
- valuesArray.exit = 'internal-as-outbound';
301
- __gaTrackerNotSend( valuesArray );
302
- };
303
- var __gaTrackerNoRedirectCrossHostname = function() {
304
- valuesArray.exit = 'cross-hostname';
305
- __gaTrackerNotSend( valuesArray );
306
- };
307
-
308
- if ( target || type == 'mailto' || type == 'tel' ) { /* If target opens a new window then just track */
309
- if ( type == 'download' ) {
310
- fieldsArray = {
311
- hitType : 'event',
312
- eventCategory : 'download',
313
- eventAction : action || link,
314
- eventLabel : label || valuesArray.title,
315
- };
316
-
317
- __gaTrackerSend( valuesArray, fieldsArray );
318
- } else if ( type == 'tel' ) {
319
- fieldsArray = {
320
- hitType : 'event',
321
- eventCategory : 'tel',
322
- eventAction : action || link,
323
- eventLabel : label || valuesArray.title.replace('tel:', ''),
324
- };
325
-
326
- __gaTrackerSend( valuesArray, fieldsArray );
327
- } else if ( type == 'mailto' ) {
328
- fieldsArray = {
329
- hitType : 'event',
330
- eventCategory : 'mailto',
331
- eventAction : action || link,
332
- eventLabel : label || valuesArray.title.replace('mailto:', ''),
333
- };
334
-
335
- __gaTrackerSend( valuesArray, fieldsArray );
336
- } else if ( type == 'internal-as-outbound' ) {
337
- fieldsArray = {
338
- hitType : 'event',
339
- eventCategory : internalAsOutboundCategory,
340
- eventAction : action || link,
341
- eventLabel : label || valuesArray.title,
342
- };
343
-
344
- __gaTrackerSend( valuesArray, fieldsArray );
345
- } else if ( type == 'external' ) {
346
- fieldsArray = {
347
- hitType: 'event',
348
- eventCategory:'outbound-link',
349
- eventAction: action || link,
350
- eventLabel: label || valuesArray.title,
351
- };
352
-
353
- __gaTrackerSend( valuesArray, fieldsArray );
354
- } else if ( type == 'cross-hostname' ) {
355
- fieldsArray = {
356
- hitType: 'event',
357
- eventCategory:'cross-hostname',
358
- eventAction: action || link,
359
- eventLabel: label || valuesArray.title,
360
- };
361
-
362
- __gaTrackerSend( valuesArray, fieldsArray );
363
- } else {
364
- if ( type && type != 'internal' ) {
365
- fieldsArray = {
366
- hitType: 'event',
367
- eventCategory: type,
368
- eventAction: action || link,
369
- eventLabel: label || valuesArray.title,
370
- };
371
-
372
- __gaTrackerSend( valuesArray, fieldsArray );
373
- } else {
374
- valuesArray.exit = 'type';
375
- __gaTrackerNotSend( valuesArray );
376
- }
377
- }
378
- } else {
379
- /* Prevent standard click, track then open */
380
- if ( type != 'cross-hostname' && type != 'external' && type != 'internal-as-outbound' ) {
381
- if (! event.defaultPrevented ) {
382
- if ( event.preventDefault ) {
383
- event.preventDefault();
384
- } else {
385
- event.returnValue = false;
386
- }
387
- }
388
- }
389
-
390
- if ( type == 'download' ) {
391
- fieldsArray = {
392
- hitType : 'event',
393
- eventCategory : 'download',
394
- eventAction : action || link,
395
- eventLabel : label || valuesArray.title,
396
- hitCallback : __gaTrackerHitBack,
397
- };
398
-
399
- __gaTrackerSend( valuesArray, fieldsArray );
400
- } else if ( type == 'internal-as-outbound' ) {
401
- window.onbeforeunload = function(e) {
402
- if (! event.defaultPrevented ) {
403
- if ( event.preventDefault ) {
404
- event.preventDefault();
405
- } else {
406
- event.returnValue = false;
407
- }
408
- }
409
-
410
- fieldsArray = {
411
- hitType : 'event',
412
- eventCategory : internalAsOutboundCategory,
413
- eventAction : action || link,
414
- eventLabel : label || valuesArray.title,
415
- hitCallback : __gaTrackerHitBack,
416
- };
417
-
418
- if ( navigator.sendBeacon ) {
419
- fieldsArray.transport = 'beacon';
420
- }
421
-
422
- __gaTrackerSend( valuesArray, fieldsArray );
423
- setTimeout( __gaTrackerHitBack, 1000 );
424
- };
425
- } else if ( type == 'external' ) {
426
- window.onbeforeunload = function(e) {
427
- if (! event.defaultPrevented ) {
428
- if ( event.preventDefault ) {
429
- event.preventDefault();
430
- } else {
431
- event.returnValue = false;
432
- }
433
- }
434
-
435
- fieldsArray = {
436
- hitType : 'event',
437
- eventCategory : 'outbound-link',
438
- eventAction : action || link,
439
- eventLabel : label || valuesArray.title,
440
- hitCallback : __gaTrackerHitBack,
441
- };
442
-
443
- if ( navigator.sendBeacon ) {
444
- fieldsArray.transport = 'beacon';
445
- }
446
-
447
- __gaTrackerSend( valuesArray, fieldsArray );
448
- setTimeout( __gaTrackerHitBack, 1000 );
449
- };
450
- } else if ( type == 'cross-hostname' ) {
451
- window.onbeforeunload = function(e) {
452
- if (! event.defaultPrevented ) {
453
- if ( event.preventDefault ) {
454
- event.preventDefault();
455
- } else {
456
- event.returnValue = false;
457
- }
458
- }
459
-
460
- fieldsArray = {
461
- hitType : 'event',
462
- eventCategory : 'cross-hostname',
463
- eventAction : action || link,
464
- eventLabel : label || valuesArray.title,
465
- hitCallback : __gaTrackerHitBack,
466
- };
467
-
468
- if ( navigator.sendBeacon ) {
469
- fieldsArray.transport = 'beacon';
470
- }
471
-
472
- __gaTrackerSend( valuesArray, fieldsArray );
473
- setTimeout( __gaTrackerHitBack, 1000 );
474
- };
475
- } else {
476
- if ( type && type !== 'internal' ) {
477
- fieldsArray = {
478
- hitType: 'event',
479
- eventCategory: type,
480
- eventAction: action || link,
481
- eventLabel: label || valuesArray.title,
482
- hitCallback : __gaTrackerHitBack,
483
- };
484
-
485
- __gaTrackerSend( valuesArray, fieldsArray );
486
- } else {
487
- valuesArray.exit = 'type';
488
- __gaTrackerNotSend( valuesArray );
489
- }
490
- }
491
-
492
- if ( type != 'external' && type != 'cross-hostname' && type != 'internal-as-outbound' ) {
493
- /* Run hitCallback again if GA takes longer than 1 second */
494
- setTimeout( __gaTrackerHitBack, 1000 );
495
- } else {
496
- if ( type == 'external' ) {
497
- setTimeout( __gaTrackerNoRedirectExternal, 1100 );
498
- } else if ( type == 'cross-hostname' ) {
499
- setTimeout( __gaTrackerNoRedirectCrossHostname, 1100 );
500
- } else {
501
- setTimeout( __gaTrackerNoRedirectInboundAsExternal, 1100 );
502
- }
503
- }
504
- }
505
- } else {
506
- valuesArray.exit = 'internal';
507
- __gaTrackerNotSend( valuesArray );
508
- }
509
- } else {
510
- valuesArray.exit = 'notlink';
511
- __gaTrackerNotSend( valuesArray );
512
- }
513
- }
514
- var prevHash = window.location.hash;
515
- function __gaTrackerHashChangeEvent() {
516
- /* Todo: Ready this section for JS unit testing */
517
- if ( monsterinsights_frontend.hash_tracking === "true" && prevHash != window.location.hash ) {
518
- prevHash = window.location.hash;
519
- __gaTracker('set', 'page', location.pathname + location.search + location.hash );
520
- __gaTracker('send', 'pageview' );
521
- __gaTrackerLog( "Hash change to: " + location.pathname + location.search + location.hash );
522
- } else {
523
- __gaTrackerLog( "Hash change to (untracked): " + location.pathname + location.search + location.hash );
524
- }
525
- }
526
-
527
- /* Attach the event to all clicks in the document after page has loaded */
528
- var __gaTrackerWindow = window;
529
- if ( __gaTrackerWindow.addEventListener ) {
530
- __gaTrackerWindow.addEventListener(
531
- "load",
532
- function() {
533
- document.body.addEventListener(
534
- "click",
535
- __gaTrackerClickEvent,
536
- false
537
- );
538
- },
539
- false
540
- );
541
- window.addEventListener("hashchange", __gaTrackerHashChangeEvent, false );
542
- } else {
543
- if ( __gaTrackerWindow.attachEvent ) {
544
- __gaTrackerWindow.attachEvent(
545
- "onload",
546
- function() {
547
- document.body.attachEvent( "onclick", __gaTrackerClickEvent);
548
- }
549
- );
550
- window.attachEvent( "onhashchange", __gaTrackerHashChangeEvent);
551
- }
552
- }
553
-
554
- if (typeof String.prototype.endsWith !== 'function') {
555
- String.prototype.endsWith = function(suffix) {
556
- return this.indexOf(suffix, this.length - suffix.length) !== -1;
557
- };
558
- }
559
- if (typeof String.prototype.startsWith !== 'function') {
560
- String.prototype.startsWith = function(prefix) {
561
- return this.indexOf(prefix) === 0;
562
- };
563
- }
564
-
565
- if ( typeof Array.prototype.lastIndexOf !== 'function' ) {
566
- Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/) {
567
- 'use strict';
568
-
569
- if (this === void 0 || this === null) {
570
- throw new TypeError();
571
- }
572
-
573
- var n, k,
574
- t = Object(this),
575
- len = t.length >>> 0; /* jshint ignore:line */
576
- if (len === 0) {
577
- return -1;
578
- }
579
-
580
- n = len - 1;
581
- if (arguments.length > 1) {
582
- n = Number(arguments[1]);
583
- if (n != n) {
584
- n = 0;
585
- }
586
- else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) { /* jshint ignore:line */
587
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
588
- }
589
- }
590
-
591
- for (k = n >= 0 ? Math.min(n, len - 1) : len - Math.abs(n); k >= 0; k--) {
592
- if (k in t && t[k] === searchElement) {
593
- return k;
594
- }
595
- }
596
- return -1;
597
- };
598
- }
599
- };
600
- var MonsterInsightsObject = new MonsterInsights();
1
+ /**
2
+ * Developer's Notice:
3
+ *
4
+ * Note: JS in this file (and this file itself) is not garunteed backwards compatibility. JS can be added, changed or removed at any time without notice.
5
+ * For more information see the `Backwards Compatibility Guidelines for Developers` section of the README.md file.
6
+ */
7
+ /**
8
+ * Handles:
9
+ * - JS Events handling
10
+ *
11
+ * @since 6.0.12
12
+ */
13
+ var MonsterInsights = function(){
14
+ /* MonsterInsights JS events tracking works on all major browsers, including IE starting at IE 7, via polyfills for any major JS function used that
15
+ is not supported by at least 95% of the global and/or US browser marketshare. Currently, IE 7 & 8 which as of 2/14/17 have under 0.25% global marketshare, require
16
+ us to polyfill Array.prototype.lastIndexOf, and if they continue to drop, we might remove this polyfill at some point. In that case note that events tracking
17
+ for IE 7/8 will continue to work, with the exception of events tracking of downloads. */
18
+ var lastClicked = [];
19
+ var internalAsOutboundCategory = '';
20
+
21
+ this.setLastClicked = function(valuesArray,fieldsArray,tracked){
22
+ valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
23
+ fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : [];
24
+ tracked = typeof tracked !== 'undefined' ? tracked : false;
25
+
26
+ lastClicked.valuesArray = valuesArray;
27
+ lastClicked.fieldsArray = fieldsArray;
28
+ };
29
+
30
+ this.getLastClicked = function () {
31
+ return lastClicked;
32
+ };
33
+
34
+ this.setInternalAsOutboundCategory = function( category ){
35
+ internalAsOutboundCategory = category;
36
+ };
37
+
38
+ this.getInternalAsOutboundCategory = function () {
39
+ return internalAsOutboundCategory;
40
+ };
41
+
42
+ this.sendEvent = function ( fieldsArray ) {
43
+ __gaTrackerSend( [], fieldsArray );
44
+ };
45
+
46
+ function __gaTrackerIsDebug () {
47
+ if ( window.monsterinsights_debug_mode ) {
48
+ return true;
49
+ } else {
50
+ return false;
51
+ }
52
+ }
53
+
54
+ function __gaTrackerSend ( valuesArray, fieldsArray ) {
55
+ valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
56
+ fieldsArray = typeof fieldsArray !== 'undefined' ? fieldsArray : {};
57
+
58
+ __gaTracker( 'send', fieldsArray );
59
+
60
+ lastClicked.valuesArray = valuesArray;
61
+ lastClicked.fieldsArray = fieldsArray;
62
+ lastClicked.tracked = true;
63
+ __gaTrackerLog( 'Tracked: ' + valuesArray.type );
64
+ __gaTrackerLog( lastClicked );
65
+ }
66
+
67
+ function __gaTrackerNotSend ( valuesArray ) {
68
+ valuesArray = typeof valuesArray !== 'undefined' ? valuesArray : [];
69
+
70
+ lastClicked.valuesArray = valuesArray;
71
+ lastClicked.fieldsArray = [];
72
+ lastClicked.tracked = false;
73
+ __gaTrackerLog( 'Not Tracked: ' + valuesArray.exit );
74
+ __gaTrackerLog( lastClicked );
75
+ }
76
+
77
+ function __gaTrackerLog ( message ) {
78
+ if ( __gaTrackerIsDebug() ) {
79
+ console.dir( message );
80
+ }
81
+ }
82
+
83
+ function __gaTrackerStringTrim( x ) {
84
+ return x.replace(/^\s+|\s+$/gm,'');
85
+ }
86
+
87
+ function __gaTrackerGetDomain() {
88
+ var i=0,currentdomain=document.domain,p=currentdomain.split('.'),s='_gd'+(new Date()).getTime();
89
+ while(i<(p.length-1) && document.cookie.indexOf(s+'='+s)==-1){
90
+ currentdomain = p.slice(-1-(++i)).join('.');
91
+ document.cookie = s+"="+s+";domain="+currentdomain+";";
92
+ }
93
+ document.cookie = s+"=;expires=Thu, 01 Jan 1970 00:00:01 GMT;domain="+currentdomain+";";
94
+ return currentdomain;
95
+ }
96
+
97
+ function __gaTrackerGetExtension( extension ) {
98
+ extension = extension.toString();
99
+ extension = extension.substring( 0, (extension.indexOf( "#" ) == -1 ) ? extension.length : extension.indexOf( "#" ) ); /* Remove the anchor at the end, if there is one */
100
+ extension = extension.substring( 0, (extension.indexOf( "?" ) == -1 ) ? extension.length : extension.indexOf( "?" ) ); /* Remove the query after the file name, if there is one */
101
+ extension = extension.substring( extension.lastIndexOf( "/" ) + 1, extension.length ); /* Remove everything before the last slash in the path */
102
+ if ( extension.length > 0 && extension.indexOf('.') !== -1 ) { /* If there's a period left in the URL, then there's a extension. Else it is not a extension. */
103
+ extension = extension.substring( extension.indexOf( "." ) + 1 ); /* Remove everything but what's after the first period */
104
+ return extension;
105
+ } else {
106
+ return "";
107
+ }
108
+ }
109
+
110
+ function __gaTrackerLoaded() {
111
+ return typeof(__gaTracker) !== 'undefined' && __gaTracker && __gaTracker.hasOwnProperty( "loaded" ) && __gaTracker.loaded == true; /* jshint ignore:line */
112
+ }
113
+
114
+ function __gaTrackerTrackedClick( event ) {
115
+ return event.which == 1 || event.which == 2 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
116
+ }
117
+
118
+ function __gaTrackerGetDownloadExtensions() {
119
+ var download_extensions = [];
120
+ if ( typeof monsterinsights_frontend.download_extensions == 'string' ) {
121
+ download_extensions = monsterinsights_frontend.download_extensions.split(",");
122
+ }
123
+ return download_extensions;
124
+ }
125
+
126
+ function __gaTrackerGetInboundPaths() {
127
+ var inbound_paths = [];
128
+ if ( typeof monsterinsights_frontend.inbound_paths == 'string' ) {
129
+ inbound_paths = JSON.parse( monsterinsights_frontend.inbound_paths );
130
+ }
131
+
132
+ return inbound_paths;
133
+ }
134
+
135
+ function __gaTrackerTrackedClickType( event ) {
136
+ if ( event.which == 1 ) {
137
+ return 'event.which=1';
138
+ } else if ( event.which == 2 ) {
139
+ return 'event.which=2';
140
+ } else if ( event.metaKey ){
141
+ return 'metaKey';
142
+ } else if ( event.ctrlKey ) {
143
+ return 'ctrlKey';
144
+ } else if ( event.shiftKey ) {
145
+ return 'shiftKey';
146
+ } else if ( event.altKey ) {
147
+ return 'altKey';
148
+ } else {
149
+ return '';
150
+ }
151
+ }
152
+
153
+ function __gaTrackerLinkType( el ) {
154
+ var download_extensions = __gaTrackerGetDownloadExtensions();
155
+ var inbound_paths = __gaTrackerGetInboundPaths();
156
+ var type = 'unknown';
157
+ var link = el.href;
158
+ var extension = __gaTrackerGetExtension( el.href );
159
+ var currentdomain = __gaTrackerGetDomain();
160
+ var hostname = el.hostname;
161
+ var protocol = el.protocol;
162
+ var pathname = el.pathname;
163
+ link = link.toString();
164
+ var index, len;
165
+ var category = el.getAttribute("data-vars-ga-category");
166
+
167
+ if ( category ) {
168
+ return category;
169
+ }
170
+
171
+ if ( link.match( /^javascript\:/i ) ) {
172
+ type = 'internal'; /* if it's a JS link, it's internal */
173
+ } else if ( protocol && protocol.length > 0 && ( __gaTrackerStringTrim( protocol ) == 'tel' || __gaTrackerStringTrim( protocol ) == 'tel:' ) ) { /* If it's a telephone link */
174
+ type = "tel";
175
+ } else if ( protocol && protocol.length > 0 && ( __gaTrackerStringTrim( protocol ) == 'mailto' || __gaTrackerStringTrim( protocol ) == 'mailto:' ) ) { /* If it's a email */
176
+ type = "mailto";
177
+ } else if ( hostname && currentdomain && hostname.length > 0 && currentdomain.length > 0 && ! hostname.endsWith( currentdomain ) ) { /* If it's a outbound */
178
+ type = "external";
179
+ } else if ( pathname && JSON.stringify( inbound_paths ) != "{}" && pathname.length > 0 ) { /* If it's an internal as outbound */
180
+ var inbound_paths_length = inbound_paths.length;
181
+ for ( var inbound_paths_index = 0; inbound_paths_index < inbound_paths_length; inbound_paths_index ++ ) {
182
+ if ( inbound_paths[ inbound_paths_index ].path && inbound_paths[ inbound_paths_index ].label && inbound_paths[ inbound_paths_index ].path.length > 0 && inbound_paths[ inbound_paths_index ].label.length > 0 && pathname.startsWith( inbound_paths[ inbound_paths_index ].path ) ) {
183
+ type = "internal-as-outbound";
184
+ internalAsOutboundCategory = "outbound-link-" + inbound_paths[ inbound_paths_index ].label;
185
+ break;
186
+ }
187
+ }
188
+ /* Enable window.monsterinsights_experimental_mode at your own risk. We might eventually remove it. Also you may/can/will burn through GA quota for your property quickly. */
189
+ } else if ( hostname && window.monsterinsights_experimental_mode && hostname.length > 0 && document.domain.length > 0 && hostname !== document.domain ) { /* If it's a cross-hostname link */
190
+ type = "cross-hostname";
191
+ }
192
+
193
+ if ( extension && ( type === 'unknown' || 'external' === type ) && download_extensions.length > 0 && extension.length > 0 ) { /* If it's a download */
194
+ for ( index = 0, len = download_extensions.length; index < len; ++index ) {
195
+ if ( download_extensions[ index ].length > 0 && ( link.endsWith( download_extensions[ index ] ) || download_extensions[ index ] == extension ) ) {
196
+ type = "download";
197
+ break;
198
+ }
199
+ }
200
+ }
201
+
202
+ if ( type === 'unknown' ) {
203
+ type = 'internal';
204
+ }
205
+ return type;
206
+ }
207
+
208
+ function __gaTrackerLinkTarget( el, event ) {
209
+
210
+ /* Is actual target set and not _(self|parent|top)? */
211
+ var target = ( el.target && !el.target.match( /^_(self|parent|top)$/i ) ) ? el.target : false;
212
+
213
+ /* Assume a target if Ctrl|shift|meta-click */
214
+ if ( event.ctrlKey || event.shiftKey || event.metaKey || event.which == 2 ) {
215
+ target = "_blank";
216
+ }
217
+ return target;
218
+ }
219
+
220
+ function __gaTrackerClickEvent( event ) {
221
+ var el = event.srcElement || event.target;
222
+ var valuesArray = [];
223
+ var fieldsArray;
224
+
225
+ /* Start Values Array */
226
+ valuesArray.el = el;
227
+ valuesArray.ga_loaded = __gaTrackerLoaded();
228
+ valuesArray.click_type = __gaTrackerTrackedClickType( event );
229
+
230
+ /* If GA is blocked or not loaded, or not main|middle|touch click then don't track */
231
+ if ( ! __gaTrackerLoaded() || ! __gaTrackerTrackedClick( event ) ) {
232
+ valuesArray.exit = 'loaded';
233
+ __gaTrackerNotSend( valuesArray );
234
+ return;
235
+ }
236
+
237
+ /* Loop up the DOM tree through parent elements if clicked element is not a link (eg: an image inside a link) */
238
+ while ( el && (typeof el.tagName == 'undefined' || el.tagName.toLowerCase() != 'a' || ! el.href ) ) {
239
+ el = el.parentNode;
240
+ }
241
+
242
+ /* if a link with valid href has been clicked */
243
+ if ( el && el.href && ! el.hasAttribute('xlink:href') ) {
244
+ var link = el.href; /* What link are we tracking */
245
+ var extension = __gaTrackerGetExtension( el.href ); /* What extension is this link */
246
+ var download_extensions = __gaTrackerGetDownloadExtensions(); /* Let's get the extensions to track */
247
+ var inbound_paths = __gaTrackerGetInboundPaths(); /* Let's get the internal paths to track */
248
+ var home_url = monsterinsights_frontend.home_url; /* Let's get the url to compare for external/internal use */
249
+ var currentdomain = __gaTrackerGetDomain(); /* What domain are we on? */
250
+ var type = __gaTrackerLinkType( el ); /* What type of link is this? */
251
+ var target = __gaTrackerLinkTarget( el, event ); /* Is a new tab/window being opened? */
252
+ var action = el.getAttribute("data-vars-ga-action");
253
+ var label = el.getAttribute("data-vars-ga-label");
254
+
255
+ /* Element */
256
+ valuesArray.el = el; /* el is an a element so we can parse it */
257
+ valuesArray.el_href = el.href; /* "http://example.com:3000/pathname/?search=test#hash" */
258
+ valuesArray.el_protocol = el.protocol; /* "http:" */
259
+ valuesArray.el_hostname = el.hostname; /* "example.com" */
260
+ valuesArray.el_port = el.port; /* "3000" */
261
+ valuesArray.el_pathname = el.pathname; /* "/pathname/" */
262
+ valuesArray.el_search = el.search; /* "?search=test" */
263
+ valuesArray.el_hash = el.hash; /* "#hash" */
264
+ valuesArray.el_host = el.host; /* "example.com:3000" */
265
+
266
+ /* Settings */
267
+ valuesArray.debug_mode = __gaTrackerIsDebug(); /* "example.com:3000" */
268
+ valuesArray.download_extensions = download_extensions; /* Let's get the extensions to track */
269
+ valuesArray.inbound_paths = inbound_paths; /* Let's get the internal paths to track */
270
+ valuesArray.home_url = home_url; /* Let's get the url to compare for external/internal use */
271
+
272
+ /* Parsed/Logic */
273
+ valuesArray.link = link; /* What link are we tracking */
274
+ valuesArray.extension = extension; /* What extension is this link */
275
+ valuesArray.type = type; /* What type of link is this */
276
+ valuesArray.target = target; /* Is a new tab/window being opened? */
277
+ valuesArray.title = el.title || el.innerText || el.getAttribute('aria-label') || el.textContent; /* Try link title, then text content */
278
+
279
+ /* Let's track everything but internals (that aren't internal-as-externals) and javascript */
280
+ if ( type !== 'internal' && type !== 'javascript' ) {
281
+
282
+ var __gaTrackerHitBackRun = false; /* Tracker has not yet run */
283
+
284
+ /* HitCallback to open link in same window after tracker */
285
+ var __gaTrackerHitBack = function() {
286
+ /* Run the hitback only once */
287
+ if ( __gaTrackerHitBackRun ){
288
+ return;
289
+ }
290
+ __gaTrackerHitBackRun = true;
291
+ window.location.href = link;
292
+ };
293
+
294
+ var __gaTrackerNoRedirectExternal = function() {
295
+ valuesArray.exit = 'external';
296
+ __gaTrackerNotSend( valuesArray );
297
+ };
298
+
299
+ var __gaTrackerNoRedirectInboundAsExternal = function() {
300
+ valuesArray.exit = 'internal-as-outbound';
301
+ __gaTrackerNotSend( valuesArray );
302
+ };
303
+ var __gaTrackerNoRedirectCrossHostname = function() {
304
+ valuesArray.exit = 'cross-hostname';
305
+ __gaTrackerNotSend( valuesArray );
306
+ };
307
+
308
+ if ( target || type == 'mailto' || type == 'tel' ) { /* If target opens a new window then just track */
309
+ if ( type == 'download' ) {
310
+ fieldsArray = {
311
+ hitType : 'event',
312
+ eventCategory : 'download',
313
+ eventAction : action || link,
314
+ eventLabel : label || valuesArray.title,
315
+ };
316
+
317
+ __gaTrackerSend( valuesArray, fieldsArray );
318
+ } else if ( type == 'tel' ) {
319
+ fieldsArray = {
320
+ hitType : 'event',
321
+ eventCategory : 'tel',
322
+ eventAction : action || link,
323
+ eventLabel : label || valuesArray.title.replace('tel:', ''),
324
+ };
325
+
326
+ __gaTrackerSend( valuesArray, fieldsArray );
327
+ } else if ( type == 'mailto' ) {
328
+ fieldsArray = {
329
+ hitType : 'event',
330
+ eventCategory : 'mailto',
331
+ eventAction : action || link,
332
+ eventLabel : label || valuesArray.title.replace('mailto:', ''),
333
+ };
334
+
335
+ __gaTrackerSend( valuesArray, fieldsArray );
336
+ } else if ( type == 'internal-as-outbound' ) {
337
+ fieldsArray = {
338
+ hitType : 'event',
339
+ eventCategory : internalAsOutboundCategory,
340
+ eventAction : action || link,
341
+ eventLabel : label || valuesArray.title,
342
+ };
343
+
344
+ __gaTrackerSend( valuesArray, fieldsArray );
345
+ } else if ( type == 'external' ) {
346
+ fieldsArray = {
347
+ hitType: 'event',
348
+ eventCategory:'outbound-link',
349
+ eventAction: action || link,
350
+ eventLabel: label || valuesArray.title,
351
+ };
352
+
353
+ __gaTrackerSend( valuesArray, fieldsArray );
354
+ } else if ( type == 'cross-hostname' ) {
355
+ fieldsArray = {
356
+ hitType: 'event',
357
+ eventCategory:'cross-hostname',
358
+ eventAction: action || link,
359
+ eventLabel: label || valuesArray.title,
360
+ };
361
+
362
+ __gaTrackerSend( valuesArray, fieldsArray );
363
+ } else {
364
+ if ( type && type != 'internal' ) {
365
+ fieldsArray = {
366
+ hitType: 'event',
367
+ eventCategory: type,
368
+ eventAction: action || link,
369
+ eventLabel: label || valuesArray.title,
370
+ };
371
+
372
+ __gaTrackerSend( valuesArray, fieldsArray );
373
+ } else {
374
+ valuesArray.exit = 'type';
375
+ __gaTrackerNotSend( valuesArray );
376
+ }
377
+ }
378
+ } else {
379
+ /* Prevent standard click, track then open */
380
+ if ( type != 'cross-hostname' && type != 'external' && type != 'internal-as-outbound' ) {
381
+ if (! event.defaultPrevented ) {
382
+ if ( event.preventDefault ) {
383
+ event.preventDefault();
384
+ } else {
385
+ event.returnValue = false;
386
+ }
387
+ }
388
+ }
389
+
390
+ if ( type == 'download' ) {
391
+ fieldsArray = {
392
+ hitType : 'event',
393
+ eventCategory : 'download',
394
+ eventAction : action || link,
395
+ eventLabel : label || valuesArray.title,
396
+ hitCallback : __gaTrackerHitBack,
397
+ };
398
+
399
+ __gaTrackerSend( valuesArray, fieldsArray );
400
+ } else if ( type == 'internal-as-outbound' ) {
401
+ window.onbeforeunload = function(e) {
402
+ if (! event.defaultPrevented ) {
403
+ if ( event.preventDefault ) {
404
+ event.preventDefault();
405
+ } else {
406
+ event.returnValue = false;
407
+ }
408
+ }
409
+
410
+ fieldsArray = {
411
+ hitType : 'event',
412
+ eventCategory : internalAsOutboundCategory,
413
+ eventAction : action || link,
414
+ eventLabel : label || valuesArray.title,
415
+ hitCallback : __gaTrackerHitBack,
416
+ };
417
+
418
+ if ( navigator.sendBeacon ) {
419
+ fieldsArray.transport = 'beacon';
420
+ }
421
+
422
+ __gaTrackerSend( valuesArray, fieldsArray );
423
+ setTimeout( __gaTrackerHitBack, 1000 );
424
+ };
425
+ } else if ( type == 'external' ) {
426
+ window.onbeforeunload = function(e) {
427
+ if (! event.defaultPrevented ) {
428
+ if ( event.preventDefault ) {
429
+ event.preventDefault();
430
+ } else {
431
+ event.returnValue = false;
432
+ }
433
+ }
434
+
435
+ fieldsArray = {
436
+ hitType : 'event',
437
+ eventCategory : 'outbound-link',
438
+ eventAction : action || link,
439
+ eventLabel : label || valuesArray.title,
440
+ hitCallback : __gaTrackerHitBack,
441
+ };
442
+
443
+ if ( navigator.sendBeacon ) {
444
+ fieldsArray.transport = 'beacon';
445
+ }
446
+
447
+ __gaTrackerSend( valuesArray, fieldsArray );
448
+ setTimeout( __gaTrackerHitBack, 1000 );
449
+ };
450
+ } else if ( type == 'cross-hostname' ) {
451
+ window.onbeforeunload = function(e) {
452
+ if (! event.defaultPrevented ) {
453
+ if ( event.preventDefault ) {
454
+ event.preventDefault();
455
+ } else {
456
+ event.returnValue = false;
457
+ }
458
+ }
459
+
460
+ fieldsArray = {
461
+ hitType : 'event',
462
+ eventCategory : 'cross-hostname',
463
+ eventAction : action || link,
464
+ eventLabel : label || valuesArray.title,
465
+ hitCallback : __gaTrackerHitBack,
466
+ };
467
+
468
+ if ( navigator.sendBeacon ) {
469
+ fieldsArray.transport = 'beacon';
470
+ }
471
+
472
+ __gaTrackerSend( valuesArray, fieldsArray );
473
+ setTimeout( __gaTrackerHitBack, 1000 );
474
+ };
475
+ } else {
476
+ if ( type && type !== 'internal' ) {
477
+ fieldsArray = {
478
+ hitType: 'event',
479
+ eventCategory: type,
480
+ eventAction: action || link,
481
+ eventLabel: label || valuesArray.title,
482
+ hitCallback : __gaTrackerHitBack,
483
+ };
484
+
485
+ __gaTrackerSend( valuesArray, fieldsArray );
486
+ } else {
487
+ valuesArray.exit = 'type';
488
+ __gaTrackerNotSend( valuesArray );
489
+ }
490
+ }
491
+
492
+ if ( type != 'external' && type != 'cross-hostname' && type != 'internal-as-outbound' ) {
493
+ /* Run hitCallback again if GA takes longer than 1 second */
494
+ setTimeout( __gaTrackerHitBack, 1000 );
495
+ } else {
496
+ if ( type == 'external' ) {
497
+ setTimeout( __gaTrackerNoRedirectExternal, 1100 );
498
+ } else if ( type == 'cross-hostname' ) {
499
+ setTimeout( __gaTrackerNoRedirectCrossHostname, 1100 );
500
+ } else {
501
+ setTimeout( __gaTrackerNoRedirectInboundAsExternal, 1100 );
502
+ }
503
+ }
504
+ }
505
+ } else {
506
+ valuesArray.exit = 'internal';
507
+ __gaTrackerNotSend( valuesArray );
508
+ }
509
+ } else {
510
+ valuesArray.exit = 'notlink';
511
+ __gaTrackerNotSend( valuesArray );
512
+ }
513
+ }
514
+ var prevHash = window.location.hash;
515
+ function __gaTrackerHashChangeEvent() {
516
+ /* Todo: Ready this section for JS unit testing */
517
+ if ( monsterinsights_frontend.hash_tracking === "true" && prevHash != window.location.hash ) {
518
+ prevHash = window.location.hash;
519
+ __gaTracker('set', 'page', location.pathname + location.search + location.hash );
520
+ __gaTracker('send', 'pageview' );
521
+ __gaTrackerLog( "Hash change to: " + location.pathname + location.search + location.hash );
522
+ } else {
523
+ __gaTrackerLog( "Hash change to (untracked): " + location.pathname + location.search + location.hash );
524
+ }
525
+ }
526
+
527
+ /* Attach the event to all clicks in the document after page has loaded */
528
+ var __gaTrackerWindow = window;
529
+ if ( __gaTrackerWindow.addEventListener ) {
530
+ __gaTrackerWindow.addEventListener(
531
+ "load",
532
+ function() {
533
+ document.body.addEventListener(
534
+ "click",
535
+ __gaTrackerClickEvent,
536
+ false
537
+ );
538
+ },
539
+ false
540
+ );
541
+ window.addEventListener("hashchange", __gaTrackerHashChangeEvent, false );
542
+ } else {
543
+ if ( __gaTrackerWindow.attachEvent ) {
544
+ __gaTrackerWindow.attachEvent(
545
+ "onload",
546
+ function() {
547
+ document.body.attachEvent( "onclick", __gaTrackerClickEvent);
548
+ }
549
+ );
550
+ window.attachEvent( "onhashchange", __gaTrackerHashChangeEvent);
551
+ }
552
+ }
553
+
554
+ if (typeof String.prototype.endsWith !== 'function') {
555
+ String.prototype.endsWith = function(suffix) {
556
+ return this.indexOf(suffix, this.length - suffix.length) !== -1;
557
+ };
558
+ }
559
+ if (typeof String.prototype.startsWith !== 'function') {
560
+ String.prototype.startsWith = function(prefix) {
561
+ return this.indexOf(prefix) === 0;
562
+ };
563
+ }
564
+
565
+ if ( typeof Array.prototype.lastIndexOf !== 'function' ) {
566
+ Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/) {
567
+ 'use strict';
568
+
569
+ if (this === void 0 || this === null) {
570
+ throw new TypeError();
571
+ }
572
+
573
+ var n, k,
574
+ t = Object(this),
575
+ len = t.length >>> 0; /* jshint ignore:line */
576
+ if (len === 0) {
577
+ return -1;
578
+ }
579
+
580
+ n = len - 1;
581
+ if (arguments.length > 1) {
582
+ n = Number(arguments[1]);
583
+ if (n != n) {
584
+ n = 0;
585
+ }
586
+ else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) { /* jshint ignore:line */
587
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
588
+ }
589
+ }
590
+
591
+ for (k = n >= 0 ? Math.min(n, len - 1) : len - Math.abs(n); k >= 0; k--) {
592
+ if (k in t && t[k] === searchElement) {
593
+ return k;
594
+ }
595
+ }
596
+ return -1;
597
+ };
598
+ }
599
+ };
600
+ var MonsterInsightsObject = new MonsterInsights();
assets/js/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/lib/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
assets/lib/pandora/class-am-dashboard-widget-extend-feed.php CHANGED
@@ -1,130 +1,130 @@
1
- <?php
2
-
3
- if ( ! class_exists( 'AM_Dashboard_Widget_Extend_Feed' ) ) {
4
- /**
5
- * Awesome Motive Events and News Feed.
6
- *
7
- * This appends additional blog feeds to the WordPress Events and News Feed Widget
8
- * available in the WP-Admin Dashboard.
9
- *
10
- * @package AwesomeMotive
11
- * @author AwesomeMotive Team
12
- * @license GPL-2.0+
13
- * @copyright Copyright (c) 2018, Awesome Motive LLC
14
- * @version 1.0.0
15
- */
16
- class AM_Dashboard_Widget_Extend_Feed {
17
-
18
- /**
19
- * The number of feed items to show.
20
- *
21
- * @since 1.0.0
22
- *
23
- * @var int
24
- */
25
- const FEED_COUNT = 6;
26
-
27
- /**
28
- * Construct.
29
- *
30
- * @since 1.0.0
31
- */
32
- public function __construct() {
33
-
34
- // Actions.
35
- add_action( 'wp_feed_options', array( $this, 'dashboard_update_feed_urls' ), 10, 2 );
36
-
37
- // Filters.
38
- add_filter( 'dashboard_secondary_items', array( $this, 'dashboard_items_count' ) );
39
- }
40
-
41
- /**
42
- * Set the number of feed items to show.
43
- *
44
- * @since 1.0.0
45
- *
46
- * @return int Count of feed items.
47
- */
48
- public function dashboard_items_count() {
49
-
50
- /**
51
- * Apply the filters am_dashboard_feed_count for letting an admin
52
- * override this count.
53
- */
54
- return (int) apply_filters( 'am_dashboard_feed_count', self::FEED_COUNT );
55
- }
56
-
57
- /**
58
- * Update the planet feed to add other AM blog feeds.
59
- *
60
- * @since 1.0.0
61
- *
62
- * @param object $feed SimplePie feed object (passed by reference).
63
- * @param string $url URL of feed to retrieve (original planet feed url). If an array of URLs, the feeds are merged.
64
- */
65
- public function dashboard_update_feed_urls( $feed, $url ) {
66
-
67
- global $pagenow;
68
-
69
- // Return early if not on the right page.
70
- if ( 'admin-ajax.php' !== $pagenow ) {
71
- return;
72
- }
73
-
74
- /**
75
- * Return early if not on the right feed.
76
- * We want to modify the feed URLs only for the
77
- * WordPress Events & News Dashboard Widget
78
- */
79
- if ( strpos( $url, 'planet.wordpress.org' ) === false ) {
80
- return;
81
- }
82
-
83
- // Build the feed sources.
84
- $all_feed_urls = $this->get_feed_urls( $url );
85
-
86
- // Update the feed sources.
87
- $feed->set_feed_url( $all_feed_urls );
88
- }
89
-
90
- /**
91
- * Get the feed URLs for various active AM Products.
92
- *
93
- * @since 1.0.0
94
- *
95
- * @param string $url Planet Feed URL.
96
- *
97
- * @return array Array of Feed URLs.
98
- */
99
- public function get_feed_urls( $url ) {
100
-
101
- // Initialize the feeds array.
102
- $feed_urls = array(
103
- 'https://www.wpbeginner.com/feed/',
104
- 'https://www.isitwp.com/feed/',
105
- $url,
106
- );
107
-
108
- // Check if MonsterInsights is active.
109
- if ( function_exists( 'MonsterInsights' ) ) {
110
- $feed_urls[] = 'https://www.monsterinsights.com/feed/';
111
- }
112
-
113
- // Check if WPForms is active.
114
- if ( function_exists( 'wpforms' ) ) {
115
- $feed_urls[] = 'https://wpforms.com/feed/';
116
- }
117
-
118
- // Check if OptinMonster is active.
119
- if ( class_exists( 'OMAPI', false ) ) {
120
- $feed_urls[] = 'https://optinmonster.com/feed/';
121
- }
122
-
123
- // Return the feed URLs.
124
- return array_unique( $feed_urls );
125
- }
126
- }
127
-
128
- // Create an instance.
129
- new AM_Dashboard_Widget_Extend_Feed();
130
- }
1
+ <?php
2
+
3
+ if ( ! class_exists( 'AM_Dashboard_Widget_Extend_Feed' ) ) {
4
+ /**
5
+ * Awesome Motive Events and News Feed.
6
+ *
7
+ * This appends additional blog feeds to the WordPress Events and News Feed Widget
8
+ * available in the WP-Admin Dashboard.
9
+ *
10
+ * @package AwesomeMotive
11
+ * @author AwesomeMotive Team
12
+ * @license GPL-2.0+
13
+ * @copyright Copyright (c) 2018, Awesome Motive LLC
14
+ * @version 1.0.0
15
+ */
16
+ class AM_Dashboard_Widget_Extend_Feed {
17
+
18
+ /**
19
+ * The number of feed items to show.
20
+ *
21
+ * @since 1.0.0
22
+ *
23
+ * @var int
24
+ */
25
+ const FEED_COUNT = 6;
26
+
27
+ /**
28
+ * Construct.
29
+ *
30
+ * @since 1.0.0
31
+ */
32
+ public function __construct() {
33
+
34
+ // Actions.
35
+ add_action( 'wp_feed_options', array( $this, 'dashboard_update_feed_urls' ), 10, 2 );
36
+
37
+ // Filters.
38
+ add_filter( 'dashboard_secondary_items', array( $this, 'dashboard_items_count' ) );
39
+ }
40
+
41
+ /**
42
+ * Set the number of feed items to show.
43
+ *
44
+ * @since 1.0.0
45
+ *
46
+ * @return int Count of feed items.
47
+ */
48
+ public function dashboard_items_count() {
49
+
50
+ /**
51
+ * Apply the filters am_dashboard_feed_count for letting an admin
52
+ * override this count.
53
+ */
54
+ return (int) apply_filters( 'am_dashboard_feed_count', self::FEED_COUNT );
55
+ }
56
+
57
+ /**
58
+ * Update the planet feed to add other AM blog feeds.
59
+ *
60
+ * @since 1.0.0
61
+ *
62
+ * @param object $feed SimplePie feed object (passed by reference).
63
+ * @param string $url URL of feed to retrieve (original planet feed url). If an array of URLs, the feeds are merged.
64
+ */
65
+ public function dashboard_update_feed_urls( $feed, $url ) {
66
+
67
+ global $pagenow;
68
+
69
+ // Return early if not on the right page.
70
+ if ( 'admin-ajax.php' !== $pagenow ) {
71
+ return;
72
+ }
73
+
74
+ /**
75
+ * Return early if not on the right feed.
76
+ * We want to modify the feed URLs only for the
77
+ * WordPress Events & News Dashboard Widget
78
+ */
79
+ if ( strpos( $url, 'planet.wordpress.org' ) === false ) {
80
+ return;
81
+ }
82
+
83
+ // Build the feed sources.
84
+ $all_feed_urls = $this->get_feed_urls( $url );
85
+
86
+ // Update the feed sources.
87
+ $feed->set_feed_url( $all_feed_urls );
88
+ }
89
+
90
+ /**
91
+ * Get the feed URLs for various active AM Products.
92
+ *
93
+ * @since 1.0.0
94
+ *
95
+ * @param string $url Planet Feed URL.
96
+ *
97
+ * @return array Array of Feed URLs.
98
+ */
99
+ public function get_feed_urls( $url ) {
100
+
101
+ // Initialize the feeds array.
102
+ $feed_urls = array(
103
+ 'https://www.wpbeginner.com/feed/',
104
+ 'https://www.isitwp.com/feed/',
105
+ $url,
106
+ );
107
+
108
+ // Check if MonsterInsights is active.
109
+ if ( function_exists( 'MonsterInsights' ) ) {
110
+ $feed_urls[] = 'https://www.monsterinsights.com/feed/';
111
+ }
112
+
113
+ // Check if WPForms is active.
114
+ if ( function_exists( 'wpforms' ) ) {
115
+ $feed_urls[] = 'https://wpforms.com/feed/';
116
+ }
117
+
118
+ // Check if OptinMonster is active.
119
+ if ( class_exists( 'OMAPI', false ) ) {
120
+ $feed_urls[] = 'https://optinmonster.com/feed/';
121
+ }
122
+
123
+ // Return the feed URLs.
124
+ return array_unique( $feed_urls );
125
+ }
126
+ }
127
+
128
+ // Create an instance.
129
+ new AM_Dashboard_Widget_Extend_Feed();
130
+ }
assets/lib/pandora/class-am-deactivation-survey.php CHANGED
@@ -1,343 +1,343 @@
1
- <?php
2
- if ( ! class_exists( 'AM_Deactivation_Survey' ) ) {
3
- /**
4
- * Awesome Motive Deactivation Survey.
5
- *
6
- * This prompts the user for more details when they deactivate the plugin.
7
- *
8
- * @version 1.2.1
9
- * @package AwesomeMotive
10
- * @author Jared Atchison and Chris Christoff
11
- * @license GPL-2.0+
12
- * @copyright Copyright (c) 2018
13
- */
14
- class AM_Deactivation_Survey {
15
-
16
- /**
17
- * The API URL we are calling.
18
- *
19
- * @since 1.0.0
20
- * @var string
21
- */
22
- public $api_url = 'https://api.awesomemotive.com/v1/deactivation-survey/';
23
-
24
- /**
25
- * Name for this plugin.
26
- *
27
- * @since 1.0.0
28
- * @var string
29
- */
30
- public $name;
31
-
32
- /**
33
- * Unique slug for this plugin.
34
- *
35
- * @since 1.0.0
36
- * @var string
37
- */
38
- public $plugin;
39
-
40
- /**
41
- * Primary class constructor.
42
- *
43
- * @since 1.0.0
44
- * @param string $name Plugin name.
45
- * @param string $plugin Plugin slug.
46
- */
47
- public function __construct( $name = '', $plugin = '' ) {
48
-
49
- $this->name = $name;
50
- $this->plugin = $plugin;
51
-
52
- // Don't run deactivation survey on dev sites.
53
- if ( $this->is_dev_url() ) {
54
- return;
55
- }
56
-
57
- add_action( 'admin_print_scripts', array( $this, 'js' ), 20 );
58
- add_action( 'admin_print_scripts', array( $this, 'css' ) );
59
- add_action( 'admin_footer', array( $this, 'modal' ) );
60
- }
61
-
62
- /**
63
- * Checks if current site is a development one.
64
- *
65
- * @since 1.2.0
66
- * @return bool
67
- */
68
- public function is_dev_url() {
69
- // If it is an AM dev site, return false, so we can see them on our dev sites.
70
- if ( defined ('AWESOMEMOTIVE_DEV_MODE' ) && AWESOMEMOTIVE_DEV_MODE ) {
71
- return false;
72
- }
73
-
74
- $url = network_site_url( '/' );
75
- $is_local_url = false;
76
-
77
- // Trim it up
78
- $url = strtolower( trim( $url ) );
79
-
80
- // Need to get the host...so let's add the scheme so we can use parse_url
81
- if ( false === strpos( $url, 'http://' ) && false === strpos( $url, 'https://' ) ) {
82
- $url = 'http://' . $url;
83
- }
84
- $url_parts = parse_url( $url );
85
- $host = ! empty( $url_parts['host'] ) ? $url_parts['host'] : false;
86
- if ( ! empty( $url ) && ! empty( $host ) ) {
87
- if ( false !== ip2long( $host ) ) {
88
- if ( ! filter_var( $host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
89
- $is_local_url = true;
90
- }
91
- } else if ( 'localhost' === $host ) {
92
- $is_local_url = true;
93
- }
94
-
95
- $tlds_to_check = array( '.dev', '.local', ':8888' );
96
- foreach ( $tlds_to_check as $tld ) {
97
- if ( false !== strpos( $host, $tld ) ) {
98
- $is_local_url = true;
99
- continue;
100
- }
101
-
102
- }
103
- if ( substr_count( $host, '.' ) > 1 ) {
104
- $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
105
- foreach ( $subdomains_to_check as $subdomain ) {
106
- $subdomain = str_replace( '.', '(.)', $subdomain );
107
- $subdomain = str_replace( array( '*', '(.)' ), '(.*)', $subdomain );
108
- if ( preg_match( '/^(' . $subdomain . ')/', $host ) ) {
109
- $is_local_url = true;
110
- continue;
111
- }
112
- }
113
- }
114
- }
115
- return $is_local_url;
116
- }
117
-
118
- /**
119
- * Checks if current admin screen is the plugins page.
120
- *
121
- * @since 1.0.0
122
- * @return bool
123
- */
124
- public function is_plugin_page() {
125
- $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
126
- if ( empty( $screen ) ) {
127
- return false;
128
- }
129
- return ( ! empty( $screen->id ) && in_array( $screen->id, array( 'plugins', 'plugins-network' ), true ) );
130
- }
131
-
132
- /**
133
- * Survey javascript.
134
- *
135
- * @since 1.0.0
136
- */
137
- public function js() {
138
-
139
- if ( ! $this->is_plugin_page() ) {
140
- return;
141
- }
142
- ?>
143
- <script type="text/javascript">
144
- jQuery(function($){
145
- var $deactivateLink = $('#the-list').find('[data-slug="<?php echo $this->plugin; ?>"] span.deactivate a'),
146
- $overlay = $('#am-deactivate-survey-<?php echo $this->plugin; ?>'),
147
- $form = $overlay.find('form'),
148
- formOpen = false;
149
- // Plugin listing table deactivate link.
150
- $deactivateLink.on('click', function(event) {
151
- event.preventDefault();
152
- $overlay.css('display', 'table');
153
- formOpen = true;
154
- $form.find('.am-deactivate-survey-option:first-of-type input[type=radio]').focus();
155
- });
156
- // Survey radio option selected.
157
- $form.on('change', 'input[type=radio]', function(event) {
158
- event.preventDefault();
159
- $form.find('input[type=text], .error').hide();
160
- $form.find('.am-deactivate-survey-option').removeClass('selected');
161
- $(this).closest('.am-deactivate-survey-option').addClass('selected').find('input[type=text]').show();
162
- });
163
- // Survey Skip & Deactivate.
164
- $form.on('click', '.am-deactivate-survey-deactivate', function(event) {
165
- event.preventDefault();
166
- location.href = $deactivateLink.attr('href');
167
- });
168
- // Survey submit.
169
- $form.submit(function(event) {
170
- event.preventDefault();
171
- if (! $form.find('input[type=radio]:checked').val()) {
172
- $form.find('.am-deactivate-survey-footer').prepend('<span class="error"><?php echo esc_js( __( 'Please select an option', 'google-analytics-for-wordpress' ) ); ?></span>');
173
- return;
174
- }
175
- var data = {
176
- code: $form.find('.selected input[type=radio]').val(),
177
- reason: $form.find('.selected .am-deactivate-survey-option-reason').text(),
178
- details: $form.find('.selected input[type=text]').val(),
179
- site: '<?php echo esc_url( home_url() ); ?>',
180
- plugin: '<?php echo sanitize_key( $this->name ); ?>'
181
- }
182
- var submitSurvey = $.post('<?php echo $this->api_url; ?>', data);
183
- submitSurvey.always(function() {
184
- location.href = $deactivateLink.attr('href');
185
- });
186
- });
187
- // Exit key closes survey when open.
188
- $(document).keyup(function(event) {
189
- if (27 === event.keyCode && formOpen) {
190
- $overlay.hide();
191
- formOpen = false;
192
- $deactivateLink.focus();
193
- }
194
- });
195
- });
196
- </script>
197
- <?php
198
- }
199
-
200
- /**
201
- * Survey CSS.
202
- *
203
- * @since 1.0.0
204
- */
205
- public function css() {
206
-
207
- if ( ! $this->is_plugin_page() ) {
208
- return;
209
- }
210
- ?>
211
- <style type="text/css">
212
- .am-deactivate-survey-modal {
213
- display: none;
214
- table-layout: fixed;
215
- position: fixed;
216
- z-index: 9999;
217
- width: 100%;
218
- height: 100%;
219
- text-align: center;
220
- font-size: 14px;
221
- top: 0;
222
- left: 0;
223
- background: rgba(0,0,0,0.8);
224
- }
225
- .am-deactivate-survey-wrap {
226
- display: table-cell;
227
- vertical-align: middle;
228
- }
229
- .am-deactivate-survey {
230
- background-color: #fff;
231
- max-width: 550px;
232
- margin: 0 auto;
233
- padding: 30px;
234
- text-align: left;
235
- }
236
- .am-deactivate-survey .error {
237
- display: block;
238
- color: red;
239
- margin: 0 0 10px 0;
240
- }
241
- .am-deactivate-survey-title {
242
- display: block;
243
- font-size: 18px;
244
- font-weight: 700;
245
- text-transform: uppercase;
246
- border-bottom: 1px solid #ddd;
247
- padding: 0 0 18px 0;
248
- margin: 0 0 18px 0;
249
- }
250
- .am-deactivate-survey-title span {
251
- color: #999;
252
- margin-right: 10px;
253
- }
254
- .am-deactivate-survey-desc {
255
- display: block;
256
- font-weight: 600;
257
- margin: 0 0 18px 0;
258
- }
259
- .am-deactivate-survey-option {
260
- margin: 0 0 10px 0;
261
- }
262
- .am-deactivate-survey-option-input {
263
- margin-right: 10px !important;
264
- }
265
- .am-deactivate-survey-option-details {
266
- display: none;
267
- width: 90%;
268
- margin: 10px 0 0 30px;
269
- }
270
- .am-deactivate-survey-footer {
271
- margin-top: 18px;
272
- }
273
- .am-deactivate-survey-deactivate {
274
- float: right;
275
- font-size: 13px;
276
- color: #ccc;
277
- text-decoration: none;
278
- padding-top: 7px;
279
- }
280
- </style>
281
- <?php
282
- }
283
-
284
- /**
285
- * Survey modal.
286
- *
287
- * @since 1.0.0
288
- */
289
- public function modal() {
290
-
291
- if ( ! $this->is_plugin_page() ) {
292
- return;
293
- }
294
-
295
- $options = array(
296
- 1 => array(
297
- 'title' => esc_html__( 'I no longer need the plugin', 'google-analytics-for-wordpress' ),
298
- ),
299
- 2 => array(
300
- 'title' => esc_html__( 'I\'m switching to a different plugin', 'google-analytics-for-wordpress' ),
301
- 'details' => esc_html__( 'Please share which plugin', 'google-analytics-for-wordpress' ),
302
- ),
303
- 3 => array(
304
- 'title' => esc_html__( 'I couldn\'t get the plugin to work', 'google-analytics-for-wordpress' ),
305
- ),
306
- 4 => array(
307
- 'title' => esc_html__( 'It\'s a temporary deactivation', 'google-analytics-for-wordpress' ),
308
- ),
309
- 5 => array(
310
- 'title' => esc_html__( 'Other', 'google-analytics-for-wordpress' ),
311
- 'details' => esc_html__( 'Please share the reason', 'google-analytics-for-wordpress' ),
312
- ),
313
- );
314
- ?>
315
- <div class="am-deactivate-survey-modal" id="am-deactivate-survey-<?php echo $this->plugin; ?>">
316
- <div class="am-deactivate-survey-wrap">
317
- <form class="am-deactivate-survey" method="post">
318
- <span class="am-deactivate-survey-title"><span class="dashicons dashicons-testimonial"></span><?php echo ' ' . esc_html__( 'Quick Feedback', 'google-analytics-for-wordpress' ); ?></span>
319
- <span class="am-deactivate-survey-desc"><?php echo sprintf( esc_html__('If you have a moment, please share why you are deactivating %s:', 'google-analytics-for-wordpress' ), $this->name ); ?></span>
320
- <div class="am-deactivate-survey-options">
321
- <?php foreach ( $options as $id => $option ) : ?>
322
- <div class="am-deactivate-survey-option">
323
- <label for="am-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="am-deactivate-survey-option-label">
324
- <input id="am-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="am-deactivate-survey-option-input" type="radio" name="code" value="<?php echo $id; ?>" />
325
- <span class="am-deactivate-survey-option-reason"><?php echo $option['title']; ?></span>
326
- </label>
327
- <?php if ( ! empty( $option['details'] ) ) : ?>
328
- <input class="am-deactivate-survey-option-details" type="text" placeholder="<?php echo $option['details']; ?>" />
329
- <?php endif; ?>
330
- </div>
331
- <?php endforeach; ?>
332
- </div>
333
- <div class="am-deactivate-survey-footer">
334
- <button type="submit" class="am-deactivate-survey-submit button button-primary button-large"><?php echo sprintf( esc_html__('Submit %s Deactivate', 'google-analytics-for-wordpress' ), '&amp;' ); ?></button>
335
- <a href="#" class="am-deactivate-survey-deactivate"><?php echo sprintf( esc_html__('Skip %s Deactivate', 'google-analytics-for-wordpress' ), '&amp;' ); ?></a>
336
- </div>
337
- </form>
338
- </div>
339
- </div>
340
- <?php
341
- }
342
- }
343
  } // End if().
1
+ <?php
2
+ if ( ! class_exists( 'AM_Deactivation_Survey' ) ) {
3
+ /**
4
+ * Awesome Motive Deactivation Survey.
5
+ *
6
+ * This prompts the user for more details when they deactivate the plugin.
7
+ *
8
+ * @version 1.2.1
9
+ * @package AwesomeMotive
10
+ * @author Jared Atchison and Chris Christoff
11
+ * @license GPL-2.0+
12
+ * @copyright Copyright (c) 2018
13
+ */
14
+ class AM_Deactivation_Survey {
15
+
16
+ /**
17
+ * The API URL we are calling.
18
+ *
19
+ * @since 1.0.0
20
+ * @var string
21
+ */
22
+ public $api_url = 'https://api.awesomemotive.com/v1/deactivation-survey/';
23
+
24
+ /**
25
+ * Name for this plugin.
26
+ *
27
+ * @since 1.0.0
28
+ * @var string
29
+ */
30
+ public $name;
31
+
32
+ /**
33
+ * Unique slug for this plugin.
34
+ *
35
+ * @since 1.0.0
36
+ * @var string
37
+ */
38
+ public $plugin;
39
+
40
+ /**
41
+ * Primary class constructor.
42
+ *
43
+ * @since 1.0.0
44
+ * @param string $name Plugin name.
45
+ * @param string $plugin Plugin slug.
46
+ */
47
+ public function __construct( $name = '', $plugin = '' ) {
48
+
49
+ $this->name = $name;
50
+ $this->plugin = $plugin;
51
+
52
+ // Don't run deactivation survey on dev sites.
53
+ if ( $this->is_dev_url() ) {
54
+ return;
55
+ }
56
+
57
+ add_action( 'admin_print_scripts', array( $this, 'js' ), 20 );
58
+ add_action( 'admin_print_scripts', array( $this, 'css' ) );
59
+ add_action( 'admin_footer', array( $this, 'modal' ) );
60
+ }
61
+
62
+ /**
63
+ * Checks if current site is a development one.
64
+ *
65
+ * @since 1.2.0
66
+ * @return bool
67
+ */
68
+ public function is_dev_url() {
69
+ // If it is an AM dev site, return false, so we can see them on our dev sites.
70
+ if ( defined ('AWESOMEMOTIVE_DEV_MODE' ) && AWESOMEMOTIVE_DEV_MODE ) {
71
+ return false;
72
+ }
73
+
74
+ $url = network_site_url( '/' );
75
+ $is_local_url = false;
76
+
77
+ // Trim it up
78
+ $url = strtolower( trim( $url ) );
79
+
80
+ // Need to get the host...so let's add the scheme so we can use parse_url
81
+ if ( false === strpos( $url, 'http://' ) && false === strpos( $url, 'https://' ) ) {
82
+ $url = 'http://' . $url;
83
+ }
84
+ $url_parts = parse_url( $url );
85
+ $host = ! empty( $url_parts['host'] ) ? $url_parts['host'] : false;
86
+ if ( ! empty( $url ) && ! empty( $host ) ) {
87
+ if ( false !== ip2long( $host ) ) {
88
+ if ( ! filter_var( $host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
89
+ $is_local_url = true;
90
+ }
91
+ } else if ( 'localhost' === $host ) {
92
+ $is_local_url = true;
93
+ }
94
+
95
+ $tlds_to_check = array( '.dev', '.local', ':8888' );
96
+ foreach ( $tlds_to_check as $tld ) {
97
+ if ( false !== strpos( $host, $tld ) ) {
98
+ $is_local_url = true;
99
+ continue;
100
+ }
101
+
102
+ }
103
+ if ( substr_count( $host, '.' ) > 1 ) {
104
+ $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
105
+ foreach ( $subdomains_to_check as $subdomain ) {
106
+ $subdomain = str_replace( '.', '(.)', $subdomain );
107
+ $subdomain = str_replace( array( '*', '(.)' ), '(.*)', $subdomain );
108
+ if ( preg_match( '/^(' . $subdomain . ')/', $host ) ) {
109
+ $is_local_url = true;
110
+ continue;
111
+ }
112
+ }
113
+ }
114
+ }
115
+ return $is_local_url;
116
+ }
117
+
118
+ /**
119
+ * Checks if current admin screen is the plugins page.
120
+ *
121
+ * @since 1.0.0
122
+ * @return bool
123
+ */
124
+ public function is_plugin_page() {
125
+ $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
126
+ if ( empty( $screen ) ) {
127
+ return false;
128
+ }
129
+ return ( ! empty( $screen->id ) && in_array( $screen->id, array( 'plugins', 'plugins-network' ), true ) );
130
+ }
131
+
132
+ /**
133
+ * Survey javascript.
134
+ *
135
+ * @since 1.0.0
136
+ */
137
+ public function js() {
138
+
139
+ if ( ! $this->is_plugin_page() ) {
140
+ return;
141
+ }
142
+ ?>
143
+ <script type="text/javascript">
144
+ jQuery(function($){
145
+ var $deactivateLink = $('#the-list').find('[data-slug="<?php echo $this->plugin; ?>"] span.deactivate a'),
146
+ $overlay = $('#am-deactivate-survey-<?php echo $this->plugin; ?>'),
147
+ $form = $overlay.find('form'),
148
+ formOpen = false;
149
+ // Plugin listing table deactivate link.
150
+ $deactivateLink.on('click', function(event) {
151
+ event.preventDefault();
152
+ $overlay.css('display', 'table');
153
+ formOpen = true;
154
+ $form.find('.am-deactivate-survey-option:first-of-type input[type=radio]').focus();
155
+ });
156
+ // Survey radio option selected.
157
+ $form.on('change', 'input[type=radio]', function(event) {
158
+ event.preventDefault();
159
+ $form.find('input[type=text], .error').hide();
160
+ $form.find('.am-deactivate-survey-option').removeClass('selected');
161
+ $(this).closest('.am-deactivate-survey-option').addClass('selected').find('input[type=text]').show();
162
+ });
163
+ // Survey Skip & Deactivate.
164
+ $form.on('click', '.am-deactivate-survey-deactivate', function(event) {
165
+ event.preventDefault();
166
+ location.href = $deactivateLink.attr('href');
167
+ });
168
+ // Survey submit.
169
+ $form.submit(function(event) {
170
+ event.preventDefault();
171
+ if (! $form.find('input[type=radio]:checked').val()) {
172
+ $form.find('.am-deactivate-survey-footer').prepend('<span class="error"><?php echo esc_js( __( 'Please select an option', 'google-analytics-for-wordpress' ) ); ?></span>');
173
+ return;
174
+ }
175
+ var data = {
176
+ code: $form.find('.selected input[type=radio]').val(),
177
+ reason: $form.find('.selected .am-deactivate-survey-option-reason').text(),
178
+ details: $form.find('.selected input[type=text]').val(),
179
+ site: '<?php echo esc_url( home_url() ); ?>',
180
+ plugin: '<?php echo sanitize_key( $this->name ); ?>'
181
+ }
182
+ var submitSurvey = $.post('<?php echo $this->api_url; ?>', data);
183
+ submitSurvey.always(function() {
184
+ location.href = $deactivateLink.attr('href');
185
+ });
186
+ });
187
+ // Exit key closes survey when open.
188
+ $(document).keyup(function(event) {
189
+ if (27 === event.keyCode && formOpen) {
190
+ $overlay.hide();
191
+ formOpen = false;
192
+ $deactivateLink.focus();
193
+ }
194
+ });
195
+ });
196
+ </script>
197
+ <?php
198
+ }
199
+
200
+ /**
201
+ * Survey CSS.
202
+ *
203
+ * @since 1.0.0
204
+ */
205
+ public function css() {
206
+
207
+ if ( ! $this->is_plugin_page() ) {
208
+ return;
209
+ }
210
+ ?>
211
+ <style type="text/css">
212
+ .am-deactivate-survey-modal {
213
+ display: none;
214
+ table-layout: fixed;
215
+ position: fixed;
216
+ z-index: 9999;
217
+ width: 100%;
218
+ height: 100%;
219
+ text-align: center;
220
+ font-size: 14px;
221
+ top: 0;
222
+ left: 0;
223
+ background: rgba(0,0,0,0.8);
224
+ }
225
+ .am-deactivate-survey-wrap {
226
+ display: table-cell;
227
+ vertical-align: middle;
228
+ }
229
+ .am-deactivate-survey {
230
+ background-color: #fff;
231
+ max-width: 550px;
232
+ margin: 0 auto;
233
+ padding: 30px;
234
+ text-align: left;
235
+ }
236
+ .am-deactivate-survey .error {
237
+ display: block;
238
+ color: red;
239
+ margin: 0 0 10px 0;
240
+ }
241
+ .am-deactivate-survey-title {
242
+ display: block;
243
+ font-size: 18px;
244
+ font-weight: 700;
245
+ text-transform: uppercase;
246
+ border-bottom: 1px solid #ddd;
247
+ padding: 0 0 18px 0;
248
+ margin: 0 0 18px 0;
249
+ }
250
+ .am-deactivate-survey-title span {
251
+ color: #999;
252
+ margin-right: 10px;
253
+ }
254
+ .am-deactivate-survey-desc {
255
+ display: block;
256
+ font-weight: 600;
257
+ margin: 0 0 18px 0;
258
+ }
259
+ .am-deactivate-survey-option {
260
+ margin: 0 0 10px 0;
261
+ }
262
+ .am-deactivate-survey-option-input {
263
+ margin-right: 10px !important;
264
+ }
265
+ .am-deactivate-survey-option-details {
266
+ display: none;
267
+ width: 90%;
268
+ margin: 10px 0 0 30px;
269
+ }
270
+ .am-deactivate-survey-footer {
271
+ margin-top: 18px;
272
+ }
273
+ .am-deactivate-survey-deactivate {
274
+ float: right;
275
+ font-size: 13px;
276
+ color: #ccc;
277
+ text-decoration: none;
278
+ padding-top: 7px;
279
+ }
280
+ </style>
281
+ <?php
282
+ }
283
+
284
+ /**
285
+ * Survey modal.
286
+ *
287
+ * @since 1.0.0
288
+ */
289
+ public function modal() {
290
+
291
+ if ( ! $this->is_plugin_page() ) {
292
+ return;
293
+ }
294
+
295
+ $options = array(
296
+ 1 => array(
297
+ 'title' => esc_html__( 'I no longer need the plugin', 'google-analytics-for-wordpress' ),
298
+ ),
299
+ 2 => array(
300
+ 'title' => esc_html__( 'I\'m switching to a different plugin', 'google-analytics-for-wordpress' ),
301
+ 'details' => esc_html__( 'Please share which plugin', 'google-analytics-for-wordpress' ),
302
+ ),
303
+ 3 => array(
304
+ 'title' => esc_html__( 'I couldn\'t get the plugin to work', 'google-analytics-for-wordpress' ),
305
+ ),
306
+ 4 => array(
307
+ 'title' => esc_html__( 'It\'s a temporary deactivation', 'google-analytics-for-wordpress' ),
308
+ ),
309
+ 5 => array(
310
+ 'title' => esc_html__( 'Other', 'google-analytics-for-wordpress' ),
311
+ 'details' => esc_html__( 'Please share the reason', 'google-analytics-for-wordpress' ),
312
+ ),
313
+ );
314
+ ?>
315
+ <div class="am-deactivate-survey-modal" id="am-deactivate-survey-<?php echo $this->plugin; ?>">
316
+ <div class="am-deactivate-survey-wrap">
317
+ <form class="am-deactivate-survey" method="post">
318
+ <span class="am-deactivate-survey-title"><span class="dashicons dashicons-testimonial"></span><?php echo ' ' . esc_html__( 'Quick Feedback', 'google-analytics-for-wordpress' ); ?></span>
319
+ <span class="am-deactivate-survey-desc"><?php echo sprintf( esc_html__('If you have a moment, please share why you are deactivating %s:', 'google-analytics-for-wordpress' ), $this->name ); ?></span>
320
+ <div class="am-deactivate-survey-options">
321
+ <?php foreach ( $options as $id => $option ) : ?>
322
+ <div class="am-deactivate-survey-option">
323
+ <label for="am-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="am-deactivate-survey-option-label">
324
+ <input id="am-deactivate-survey-option-<?php echo $this->plugin; ?>-<?php echo $id; ?>" class="am-deactivate-survey-option-input" type="radio" name="code" value="<?php echo $id; ?>" />
325
+ <span class="am-deactivate-survey-option-reason"><?php echo $option['title']; ?></span>
326
+ </label>
327
+ <?php if ( ! empty( $option['details'] ) ) : ?>
328
+ <input class="am-deactivate-survey-option-details" type="text" placeholder="<?php echo $option['details']; ?>" />
329
+ <?php endif; ?>
330
+ </div>
331
+ <?php endforeach; ?>
332
+ </div>
333
+ <div class="am-deactivate-survey-footer">
334
+ <button type="submit" class="am-deactivate-survey-submit button button-primary button-large"><?php echo sprintf( esc_html__('Submit %s Deactivate', 'google-analytics-for-wordpress' ), '&amp;' ); ?></button>
335
+ <a href="#" class="am-deactivate-survey-deactivate"><?php echo sprintf( esc_html__('Skip %s Deactivate', 'google-analytics-for-wordpress' ), '&amp;' ); ?></a>
336
+ </div>
337
+ </form>
338
+ </div>
339
+ </div>
340
+ <?php
341
+ }
342
+ }
343
  } // End if().
assets/lib/pandora/class-am-notification.php CHANGED
@@ -1,472 +1,472 @@
1
- <?php
2
-
3
- if ( ! class_exists( 'AM_Notification', false ) ) {
4
- /**
5
- * Awesome Motive Notifications
6
- *
7
- * This creates a custom post type (if it doesn't exist) and calls the API to
8
- * retrieve notifications for this product.
9
- *
10
- * @package AwesomeMotive
11
- * @author AwesomeMotive Team
12
- * @license GPL-2.0+
13
- * @copyright Copyright (c) 2018, Awesome Motive LLC
14
- * @version 1.0.7
15
- */
16
- class AM_Notification {
17
-
18
- /**
19
- * The api url we are calling.
20
- *
21
- * @since 1.0.0
22
- *
23
- * @var string
24
- */
25
- public $api_url = 'https://api.awesomemotive.com/v1/notification/';
26
-
27
- /**
28
- * A unique slug for this plugin.
29
- * (Not the WordPress plugin slug)
30
- *
31
- * @since 1.0.0
32
- *
33
- * @var string
34
- */
35
- public $plugin;
36
-
37
- /**
38
- * The current plugin version.
39
- *
40
- * @since 1.0.0
41
- *
42
- * @var string
43
- */
44
- public $plugin_version;
45
-
46
- /**
47
- * Flag if a notice has been registered.
48
- *
49
- * @since 1.0.0
50
- *
51
- * @var bool
52
- */
53
- public static $registered = false;
54
-
55
- /**
56
- * Construct.
57
- *
58
- * @since 1.0.0
59
- *
60
- * @param string $plugin The plugin slug.
61
- * @param mixed $version The version of the plugin.
62
- */
63
- public function __construct( $plugin = '', $version = 0 ) {
64
- $this->plugin = $plugin;
65
- $this->plugin_version = $version;
66
-
67
- add_action( 'init', array( $this, 'custom_post_type' ) );
68
- add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
69
- add_action( 'admin_notices', array( $this, 'display_notifications' ) );
70
- add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
71
- }
72
-
73
- /**
74
- * Registers a custom post type.
75
- *
76
- * @since 1.0.0
77
- */
78
- public function custom_post_type() {
79
- register_post_type( 'amn_' . $this->plugin, array(
80
- 'label' => $this->plugin . ' Announcements',
81
- 'can_export' => false,
82
- 'supports' => false,
83
- 'capability_type' => 'manage_options',
84
- ) );
85
- }
86
-
87
- /**
88
- * Retrieve the remote notifications if the time has expired.
89
- *
90
- * @since 1.0.0
91
- */
92
- public function get_remote_notifications() {
93
- if ( ! apply_filters( 'am_notifications_display', is_super_admin() ) ) {
94
- return;
95
- }
96
-
97
- $to_check = get_option( '_amn_' . $this->plugin . '_to_check', false );
98
-
99
- if ( $to_check == false ) {
100
- // Non load balanced. Start checking in in 7 days + 2-4 days.
101
- $checktime = array();
102
- $checktime['day'] = rand( 0, 6 );
103
- $checktime['hour'] = rand( 0, 23 );
104
- $checktime['minute'] = rand( 0, 59 );
105
- $checktime['second'] = rand( 0, 59 );
106
- $checktime['offset'] = ( $checktime['day'] * DAY_IN_SECONDS ) +
107
- ( $checktime['hour'] * HOUR_IN_SECONDS ) +
108
- ( $checktime['minute'] * MINUTE_IN_SECONDS ) +
109
- $checktime['second'];
110
- $to_check = strtotime("next sunday") + $checktime['offset'];
111
- update_option( '_amn_' . $this->plugin . '_to_check', $to_check );
112
- }
113
-
114
- if ( $to_check < time() ) {
115
- $plugin_notifications = $this->get_plugin_notifications( 1 );
116
- $notification_id = null;
117
-
118
- if ( ! empty( $plugin_notifications ) ) {
119
- // Unset it from the array.
120
- $notification = $plugin_notifications[0];
121
- $notification_id = get_post_meta( $notification->ID, 'notification_id', true );
122
- }
123
-
124
- $response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
125
- 'body' => array(
126
- 'slug' => $this->plugin,
127
- 'version' => $this->plugin_version,
128
- 'last_notification' => $notification_id,
129
- ),
130
- ) ) );
131
-
132
- $data = json_decode( $response );
133
-
134
- if ( ! empty( $data->id ) ) {
135
- $notifications = array();
136
-
137
- foreach ( (array) $data->slugs as $slug ) {
138
- $notifications = array_merge(
139
- $notifications,
140
- (array) get_posts(
141
- array(
142
- 'post_type' => 'amn_' . $slug,
143
- 'post_status' => 'all',
144
- 'meta_key' => 'notification_id',
145
- 'meta_value' => $data->id,
146
- )
147
- )
148
- );
149
- }
150
-
151
- if ( empty( $notifications ) ) {
152
- $new_notification_id = wp_insert_post(
153
- array(
154
- 'post_content' => wp_kses_post( $data->content ),
155
- 'post_type' => 'amn_' . $this->plugin,
156
- )
157
- );
158
-
159
- update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
160
- update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
161
- update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
162
- update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
163
- update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
164
- update_post_meta( $new_notification_id, 'viewed', 0 );
165
- update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
166
- update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
167
- }
168
- }
169
-
170
- // Possibly revoke notifications.
171
- if ( ! empty( $data->revoked ) ) {
172
- $this->revoke_notifications( $data->revoked );
173
- }
174
-
175
- // Set the option now so we can't run this again until after 24 hours.
176
- update_option( '_amn_' . $this->plugin . '_to_check', time() + 3 * DAY_IN_SECONDS );
177
- }
178
- }
179
-
180
- /**
181
- * Get local plugin notifications that have already been set.
182
- *
183
- * @since 1.0.0
184
- *
185
- * @param integer $limit Set the limit for how many posts to retrieve.
186
- * @param array $args Any top-level arguments to add to the array.
187
- *
188
- * @return WP_Post[] WP_Post that match the query.
189
- */
190
- public function get_plugin_notifications( $limit = - 1, $args = array() ) {
191
- return get_posts(
192
- array(
193
- 'posts_per_page' => $limit,
194
- 'post_type' => 'amn_' . $this->plugin,
195
- ) + $args
196
- );
197
- }
198
-
199
- /**
200
- * Display any notifications that should be displayed.
201
- *
202
- * @since 1.0.0
203
- */
204
- public function display_notifications() {
205
- if ( ! apply_filters( 'am_notifications_display', is_super_admin() ) ) {
206
- return;
207
- }
208
-
209
- $plugin_notifications = $this->get_plugin_notifications( - 1, array(
210
- 'post_status' => 'all',
211
- 'meta_key' => 'viewed',
212
- 'meta_value' => '0',
213
- ) );
214
-
215
- $plugin_notifications = $this->validate_notifications( $plugin_notifications );
216
-
217
- if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
218
- foreach ( $plugin_notifications as $notification ) {
219
- $dismissable = get_post_meta( $notification->ID, 'dismissable', true );
220
- $type = get_post_meta( $notification->ID, 'type', true );
221
- ?>
222
- <div class="am-notification am-notification-<?php echo absint( $notification->ID ); ?> notice notice-<?php echo esc_attr( $type ); ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
223
- <?php echo wp_kses_post( $notification->post_content ); ?>
224
- </div>
225
- <script type="text/javascript">
226
- jQuery( document ).ready( function ( $ ) {
227
- $( document ).on( 'click', '.am-notification-<?php echo absint( $notification->ID ); ?> button.notice-dismiss', function ( event ) {
228
- $.post( ajaxurl, {
229
- action: 'am_notification_dismiss',
230
- notification_id: '<?php echo absint( $notification->ID ); ?>'
231
- } );
232
- } );
233
- } );
234
- </script>
235
- <?php
236
- }
237
-
238
- self::$registered = true;
239
- }
240
- }
241
-
242
- /**
243
- * Validate the notifications before displaying them.
244
- *
245
- * @since 1.0.0
246
- *
247
- * @param array $plugin_notifications An array of plugin notifications.
248
- *
249
- * @return array A filtered array of plugin notifications.
250
- */
251
- public function validate_notifications( $plugin_notifications ) {
252
- global $pagenow;
253
-
254
- foreach ( $plugin_notifications as $key => $notification ) {
255
- // Location validation.
256
- $location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
257
- $continue = false;
258
- if ( ! in_array( 'everywhere', $location, true ) ) {
259
- if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
260
- $continue = true;
261
- }
262
-
263
- if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
264
- $continue = true;
265
- }
266
-
267
- if ( ! $continue ) {
268
- unset( $plugin_notifications[ $key ] );
269
- }
270
- }
271
-
272
- // Plugin validation (OR conditional).
273
- $plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
274
- $continue = false;
275
- if ( ! empty( $plugins ) ) {
276
- foreach ( $plugins as $plugin ) {
277
- if ( is_plugin_active( $plugin ) ) {
278
- $continue = true;
279
- }
280
- }
281
-
282
- if ( ! $continue ) {
283
- unset( $plugin_notifications[ $key ] );
284
- }
285
- }
286
-
287
- // Theme validation.
288
- $theme = get_post_meta( $notification->ID, 'theme', true );
289
- $continue = (string) wp_get_theme() === $theme;
290
-
291
- if ( ! empty( $theme ) && ! $continue ) {
292
- unset( $plugin_notifications[ $key ] );
293
- }
294
-
295
- // Version validation.
296
- $version = get_post_meta( $notification->ID, 'version', true );
297
- $continue = false;
298
- if ( ! empty( $version ) ) {
299
- if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
300
- $continue = true;
301
- }
302
-
303
- if ( ! $continue ) {
304
- unset( $plugin_notifications[ $key ] );
305
- }
306
- }
307
-
308
- // Expiration validation.
309
- $expiration = get_post_meta( $notification->ID, 'expiration', true );
310
- $continue = false;
311
- if ( ! empty( $expiration ) ) {
312
- if ( $expiration > time() ) {
313
- $continue = true;
314
- }
315
-
316
- if ( ! $continue ) {
317
- unset( $plugin_notifications[ $key ] );
318
- }
319
- }
320
-
321
- // Plan validation.
322
- $plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
323
- $continue = false;
324
- if ( ! empty( $plans ) ) {
325
- $level = $this->get_plan_level();
326
- if ( in_array( $level, $plans, true ) ) {
327
- $continue = true;
328
- }
329
-
330
- if ( ! $continue ) {
331
- unset( $plugin_notifications[ $key ] );
332
- }
333
- }
334
- }
335
-
336
- return $plugin_notifications;
337
- }
338
-
339
- /**
340
- * Grab the current plan level.
341
- *
342
- * @since 1.0.0
343
- *
344
- * @return string The current plan level.
345
- */
346
- public function get_plan_level() {
347
- // Prepare variables.
348
- $key = '';
349
- $level = '';
350
-
351
- switch ( $this->plugin ) {
352
- case 'wpforms':
353
- $option = get_option( 'wpforms_license' );
354
- $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
355
- $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
356
-
357
- // Possibly check for a constant.
358
- if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
359
- $key = WPFORMS_LICENSE_KEY;
360
- }
361
- break;
362
- case 'mi-lite':
363
- case 'mi':
364
- if ( version_compare( MONSTERINSIGHTS_VERSION, '6.9.0', '>=' ) ) {
365
- if ( MonsterInsights()->license->get_site_license_type() ) {
366
- $key = MonsterInsights()->license->get_site_license_key();
367
- $type = MonsterInsights()->license->get_site_license_type();
368
- } else if ( MonsterInsights()->license->get_network_license_type() ) {
369
- $key = MonsterInsights()->license->get_network_license_key();
370
- $type = MonsterInsights()->license->get_network_license_type();
371
- }
372
-
373
- // Check key fallbacks.
374
- if ( empty( $key ) ) {
375
- $key = MonsterInsights()->license->get_license_key();
376
- }
377
- } else {
378
- $option = get_option( 'monsterinsights_license' );
379
- $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
380
- $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
381
-
382
- // Possibly check for a constant.
383
- if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
384
- $key = MONSTERINSIGHTS_LICENSE_KEY;
385
- }
386
- }
387
- break;
388
- case 'om':
389
- $option = get_option( 'optin_monster_api' );
390
- $key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
391
-
392
- // Possibly check for a constant.
393
- if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
394
- $key = OPTINMONSTER_REST_API_LICENSE_KEY;
395
- }
396
-
397
- // If the key is still empty, check for the old legacy key.
398
- if ( empty( $key ) ) {
399
- $key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
400
- }
401
- break;
402
- }
403
-
404
- // Possibly set the level to 'none' if the key is empty and no level has been set.
405
- if ( empty( $key ) && empty( $level ) ) {
406
- $level = 'none';
407
- }
408
-
409
- // Possibly set the level to 'unknown' if a key is entered, but no level can be determined (such as manually entered key)
410
- if ( ! empty( $key ) && empty( $level ) ) {
411
- $level = 'unknown';
412
- }
413
-
414
- // Normalize the level.
415
- switch ( $level ) {
416
- case 'bronze':
417
- case 'personal':
418
- $level = 'basic';
419
- break;
420
- case 'silver':
421
- case 'multi':
422
- $level = 'plus';
423
- break;
424
- case 'gold':
425
- case 'developer':
426
- $level = 'pro';
427
- break;
428
- case 'platinum':
429
- case 'master':
430
- $level = 'ultimate';
431
- break;
432
- }
433
-
434
- // Return the plan level.
435
- return $level;
436
- }
437
-
438
- /**
439
- * Dismiss the notification via AJAX.
440
- *
441
- * @since 1.0.0
442
- */
443
- public function dismiss_notification() {
444
- if ( ! apply_filters( 'am_notifications_display', is_super_admin() ) ) {
445
- die;
446
- }
447
-
448
- $notification_id = intval( $_POST['notification_id'] );
449
- update_post_meta( $notification_id, 'viewed', 1 );
450
- die;
451
- }
452
-
453
- /**
454
- * Revokes notifications.
455
- *
456
- * @since 1.0.0
457
- *
458
- * @param array $ids An array of notification IDs to revoke.
459
- */
460
- public function revoke_notifications( $ids ) {
461
- // Loop through each of the IDs and find the post that has it as meta.
462
- foreach ( (array) $ids as $id ) {
463
- $notifications = $this->get_plugin_notifications( - 1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
464
- if ( $notifications ) {
465
- foreach ( $notifications as $notification ) {
466
- update_post_meta( $notification->ID, 'viewed', 1 );
467
- }
468
- }
469
- }
470
- }
471
- }
472
- }
1
+ <?php
2
+
3
+ if ( ! class_exists( 'AM_Notification', false ) ) {
4
+ /**
5
+ * Awesome Motive Notifications
6
+ *
7
+ * This creates a custom post type (if it doesn't exist) and calls the API to
8
+ * retrieve notifications for this product.
9
+ *
10
+ * @package AwesomeMotive
11
+ * @author AwesomeMotive Team
12
+ * @license GPL-2.0+
13
+ * @copyright Copyright (c) 2018, Awesome Motive LLC
14
+ * @version 1.0.7
15
+ */
16
+ class AM_Notification {
17
+
18
+ /**
19
+ * The api url we are calling.
20
+ *
21
+ * @since 1.0.0
22
+ *
23
+ * @var string
24
+ */
25
+ public $api_url = 'https://api.awesomemotive.com/v1/notification/';
26
+
27
+ /**
28
+ * A unique slug for this plugin.
29
+ * (Not the WordPress plugin slug)
30
+ *
31
+ * @since 1.0.0
32
+ *
33
+ * @var string
34
+ */
35
+ public $plugin;
36
+
37
+ /**
38
+ * The current plugin version.
39
+ *
40
+ * @since 1.0.0
41
+ *
42
+ * @var string
43
+ */
44
+ public $plugin_version;
45
+
46
+ /**
47
+ * Flag if a notice has been registered.
48
+ *
49
+ * @since 1.0.0
50
+ *
51
+ * @var bool
52
+ */
53
+ public static $registered = false;
54
+
55
+ /**
56
+ * Construct.
57
+ *
58
+ * @since 1.0.0
59
+ *
60
+ * @param string $plugin The plugin slug.
61
+ * @param mixed $version The version of the plugin.
62
+ */
63
+ public function __construct( $plugin = '', $version = 0 ) {
64
+ $this->plugin = $plugin;
65
+ $this->plugin_version = $version;
66
+
67
+ add_action( 'init', array( $this, 'custom_post_type' ) );
68
+ add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
69
+ add_action( 'admin_notices', array( $this, 'display_notifications' ) );
70
+ add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
71
+ }
72
+
73
+ /**
74
+ * Registers a custom post type.
75
+ *
76
+ * @since 1.0.0
77
+ */
78
+ public function custom_post_type() {
79
+ register_post_type( 'amn_' . $this->plugin, array(
80
+ 'label' => $this->plugin . ' Announcements',
81
+ 'can_export' => false,
82
+ 'supports' => false,
83
+ 'capability_type' => 'manage_options',
84
+ ) );
85
+ }
86
+
87
+ /**
88
+ * Retrieve the remote notifications if the time has expired.
89
+ *
90
+ * @since 1.0.0
91
+ */
92
+ public function get_remote_notifications() {
93
+ if ( ! apply_filters( 'am_notifications_display', is_super_admin() ) ) {
94
+ return;
95
+ }
96
+
97
+ $to_check = get_option( '_amn_' . $this->plugin . '_to_check', false );
98
+
99
+ if ( $to_check == false ) {
100
+ // Non load balanced. Start checking in in 7 days + 2-4 days.
101
+ $checktime = array();
102
+ $checktime['day'] = rand( 0, 6 );
103
+ $checktime['hour'] = rand( 0, 23 );
104
+ $checktime['minute'] = rand( 0, 59 );
105
+ $checktime['second'] = rand( 0, 59 );
106
+ $checktime['offset'] = ( $checktime['day'] * DAY_IN_SECONDS ) +
107
+ ( $checktime['hour'] * HOUR_IN_SECONDS ) +
108
+ ( $checktime['minute'] * MINUTE_IN_SECONDS ) +
109
+ $checktime['second'];
110
+ $to_check = strtotime("next sunday") + $checktime['offset'];
111
+ update_option( '_amn_' . $this->plugin . '_to_check', $to_check );
112
+ }
113
+
114
+ if ( $to_check < time() ) {
115
+ $plugin_notifications = $this->get_plugin_notifications( 1 );
116
+ $notification_id = null;
117
+
118
+ if ( ! empty( $plugin_notifications ) ) {
119
+ // Unset it from the array.
120
+ $notification = $plugin_notifications[0];
121
+ $notification_id = get_post_meta( $notification->ID, 'notification_id', true );
122
+ }
123
+
124
+ $response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
125
+ 'body' => array(
126
+ 'slug' => $this->plugin,
127
+ 'version' => $this->plugin_version,
128
+ 'last_notification' => $notification_id,
129
+ ),
130
+ ) ) );
131
+
132
+ $data = json_decode( $response );
133
+
134
+ if ( ! empty( $data->id ) ) {
135
+ $notifications = array();
136
+
137
+ foreach ( (array) $data->slugs as $slug ) {
138
+ $notifications = array_merge(
139
+ $notifications,
140
+ (array) get_posts(
141
+ array(
142
+ 'post_type' => 'amn_' . $slug,
143
+ 'post_status' => 'all',
144
+ 'meta_key' => 'notification_id',
145
+ 'meta_value' => $data->id,
146
+ )
147
+ )
148
+ );
149
+ }
150
+
151
+ if ( empty( $notifications ) ) {
152
+ $new_notification_id = wp_insert_post(
153
+ array(
154
+ 'post_content' => wp_kses_post( $data->content ),
155
+ 'post_type' => 'amn_' . $this->plugin,
156
+ )
157
+ );
158
+
159
+ update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
160
+ update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
161
+ update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
162
+ update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
163
+ update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
164
+ update_post_meta( $new_notification_id, 'viewed', 0 );
165
+ update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
166
+ update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
167
+ }
168
+ }
169
+
170
+ // Possibly revoke notifications.
171
+ if ( ! empty( $data->revoked ) ) {
172
+ $this->revoke_notifications( $data->revoked );
173
+ }
174
+
175
+ // Set the option now so we can't run this again until after 24 hours.
176
+ update_option( '_amn_' . $this->plugin . '_to_check', time() + 3 * DAY_IN_SECONDS );
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Get local plugin notifications that have already been set.
182
+ *
183
+ * @since 1.0.0
184
+ *
185
+ * @param integer $limit Set the limit for how many posts to retrieve.
186
+ * @param array $args Any top-level arguments to add to the array.
187
+ *
188
+ * @return WP_Post[] WP_Post that match the query.
189
+ */
190
+ public function get_plugin_notifications( $limit = - 1, $args = array() ) {
191
+ return get_posts(
192
+ array(
193
+ 'posts_per_page' => $limit,
194
+ 'post_type' => 'amn_' . $this->plugin,
195
+ ) + $args
196
+ );
197
+ }
198
+
199
+ /**
200
+ * Display any notifications that should be displayed.
201
+ *
202
+ * @since 1.0.0
203
+ */
204
+ public function display_notifications() {
205
+ if ( ! apply_filters( 'am_notifications_display', is_super_admin() ) ) {
206
+ return;
207
+ }
208
+
209
+ $plugin_notifications = $this->get_plugin_notifications( - 1, array(
210
+ 'post_status' => 'all',
211
+ 'meta_key' => 'viewed',
212
+ 'meta_value' => '0',
213
+ ) );
214
+
215
+ $plugin_notifications = $this->validate_notifications( $plugin_notifications );
216
+
217
+ if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
218
+ foreach ( $plugin_notifications as $notification ) {
219
+ $dismissable = get_post_meta( $notification->ID, 'dismissable', true );
220
+ $type = get_post_meta( $notification->ID, 'type', true );
221
+ ?>
222
+ <div class="am-notification am-notification-<?php echo absint( $notification->ID ); ?> notice notice-<?php echo esc_attr( $type ); ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
223
+ <?php echo wp_kses_post( $notification->post_content ); ?>
224
+ </div>
225
+ <script type="text/javascript">
226
+ jQuery( document ).ready( function ( $ ) {
227
+ $( document ).on( 'click', '.am-notification-<?php echo absint( $notification->ID ); ?> button.notice-dismiss', function ( event ) {
228
+ $.post( ajaxurl, {
229
+ action: 'am_notification_dismiss',
230
+ notification_id: '<?php echo absint( $notification->ID ); ?>'
231
+ } );
232
+ } );
233
+ } );
234
+ </script>
235
+ <?php
236
+ }
237
+
238
+ self::$registered = true;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Validate the notifications before displaying them.
244
+ *
245
+ * @since 1.0.0
246
+ *
247
+ * @param array $plugin_notifications An array of plugin notifications.
248
+ *
249
+ * @return array A filtered array of plugin notifications.
250
+ */
251
+ public function validate_notifications( $plugin_notifications ) {
252
+ global $pagenow;
253
+
254
+ foreach ( $plugin_notifications as $key => $notification ) {
255
+ // Location validation.
256
+ $location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
257
+ $continue = false;
258
+ if ( ! in_array( 'everywhere', $location, true ) ) {
259
+ if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
260
+ $continue = true;
261
+ }
262
+
263
+ if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
264
+ $continue = true;
265
+ }
266
+
267
+ if ( ! $continue ) {
268
+ unset( $plugin_notifications[ $key ] );
269
+ }
270
+ }
271
+
272
+ // Plugin validation (OR conditional).
273
+ $plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
274
+ $continue = false;
275
+ if ( ! empty( $plugins ) ) {
276
+ foreach ( $plugins as $plugin ) {
277
+ if ( is_plugin_active( $plugin ) ) {
278
+ $continue = true;
279
+ }
280
+ }
281
+
282
+ if ( ! $continue ) {
283
+ unset( $plugin_notifications[ $key ] );
284
+ }
285
+ }
286
+
287
+ // Theme validation.
288
+ $theme = get_post_meta( $notification->ID, 'theme', true );
289
+ $continue = (string) wp_get_theme() === $theme;
290
+
291
+ if ( ! empty( $theme ) && ! $continue ) {
292
+ unset( $plugin_notifications[ $key ] );
293
+ }
294
+
295
+ // Version validation.
296
+ $version = get_post_meta( $notification->ID, 'version', true );
297
+ $continue = false;
298
+ if ( ! empty( $version ) ) {
299
+ if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
300
+ $continue = true;
301
+ }
302
+
303
+ if ( ! $continue ) {
304
+ unset( $plugin_notifications[ $key ] );
305
+ }
306
+ }
307
+
308
+ // Expiration validation.
309
+ $expiration = get_post_meta( $notification->ID, 'expiration', true );
310
+ $continue = false;
311
+ if ( ! empty( $expiration ) ) {
312
+ if ( $expiration > time() ) {
313
+ $continue = true;
314
+ }
315
+
316
+ if ( ! $continue ) {
317
+ unset( $plugin_notifications[ $key ] );
318
+ }
319
+ }
320
+
321
+ // Plan validation.
322
+ $plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
323
+ $continue = false;
324
+ if ( ! empty( $plans ) ) {
325
+ $level = $this->get_plan_level();
326
+ if ( in_array( $level, $plans, true ) ) {
327
+ $continue = true;
328
+ }
329
+
330
+ if ( ! $continue ) {
331
+ unset( $plugin_notifications[ $key ] );
332
+ }
333
+ }
334
+ }
335
+
336
+ return $plugin_notifications;
337
+ }
338
+
339
+ /**
340
+ * Grab the current plan level.
341
+ *
342
+ * @since 1.0.0
343
+ *
344
+ * @return string The current plan level.
345
+ */
346
+ public function get_plan_level() {
347
+ // Prepare variables.
348
+ $key = '';
349
+ $level = '';
350
+
351
+ switch ( $this->plugin ) {
352
+ case 'wpforms':
353
+ $option = get_option( 'wpforms_license' );
354
+ $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
355
+ $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
356
+
357
+ // Possibly check for a constant.
358
+ if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
359
+ $key = WPFORMS_LICENSE_KEY;
360
+ }
361
+ break;
362
+ case 'mi-lite':
363
+ case 'mi':
364
+ if ( version_compare( MONSTERINSIGHTS_VERSION, '6.9.0', '>=' ) ) {
365
+ if ( MonsterInsights()->license->get_site_license_type() ) {
366
+ $key = MonsterInsights()->license->get_site_license_key();
367
+ $type = MonsterInsights()->license->get_site_license_type();
368
+ } else if ( MonsterInsights()->license->get_network_license_type() ) {
369
+ $key = MonsterInsights()->license->get_network_license_key();
370
+ $type = MonsterInsights()->license->get_network_license_type();
371
+ }
372
+
373
+ // Check key fallbacks.
374
+ if ( empty( $key ) ) {
375
+ $key = MonsterInsights()->license->get_license_key();
376
+ }
377
+ } else {
378
+ $option = get_option( 'monsterinsights_license' );
379
+ $key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
380
+ $level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
381
+
382
+ // Possibly check for a constant.
383
+ if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
384
+ $key = MONSTERINSIGHTS_LICENSE_KEY;
385
+ }
386
+ }
387
+ break;
388
+ case 'om':
389
+ $option = get_option( 'optin_monster_api' );
390
+ $key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
391
+
392
+ // Possibly check for a constant.
393
+ if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
394
+ $key = OPTINMONSTER_REST_API_LICENSE_KEY;
395
+ }
396
+
397
+ // If the key is still empty, check for the old legacy key.
398
+ if ( empty( $key ) ) {
399
+ $key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
400
+ }
401
+ break;
402
+ }
403
+
404
+ // Possibly set the level to 'none' if the key is empty and no level has been set.
405
+ if ( empty( $key ) && empty( $level ) ) {
406
+ $level = 'none';
407
+ }
408
+
409
+ // Possibly set the level to 'unknown' if a key is entered, but no level can be determined (such as manually entered key)
410
+ if ( ! empty( $key ) && empty( $level ) ) {
411
+ $level = 'unknown';
412
+ }
413
+
414
+ // Normalize the level.
415
+ switch ( $level ) {
416
+ case 'bronze':
417
+ case 'personal':
418
+ $level = 'basic';
419
+ break;
420
+ case 'silver':
421
+ case 'multi':
422
+ $level = 'plus';
423
+ break;
424
+ case 'gold':
425
+ case 'developer':
426
+ $level = 'pro';
427
+ break;
428
+ case 'platinum':
429
+ case 'master':
430
+ $level = 'ultimate';
431
+ break;
432
+ }
433
+
434
+ // Return the plan level.
435
+ return $level;
436
+ }
437
+
438
+ /**
439
+ * Dismiss the notification via AJAX.
440
+ *
441
+ * @since 1.0.0
442
+ */
443
+ public function dismiss_notification() {
444
+ if ( ! apply_filters( 'am_notifications_display', is_super_admin() ) ) {
445
+ die;
446
+ }
447
+
448
+ $notification_id = intval( $_POST['notification_id'] );
449
+ update_post_meta( $notification_id, 'viewed', 1 );
450
+ die;
451
+ }
452
+
453
+ /**
454
+ * Revokes notifications.
455
+ *
456
+ * @since 1.0.0
457
+ *
458
+ * @param array $ids An array of notification IDs to revoke.
459
+ */
460
+ public function revoke_notifications( $ids ) {
461
+ // Loop through each of the IDs and find the post that has it as meta.
462
+ foreach ( (array) $ids as $id ) {
463
+ $notifications = $this->get_plugin_notifications( - 1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
464
+ if ( $notifications ) {
465
+ foreach ( $notifications as $notification ) {
466
+ update_post_meta( $notification->ID, 'viewed', 1 );
467
+ }
468
+ }
469
+ }
470
+ }
471
+ }
472
+ }
googleanalytics.php CHANGED
@@ -1,808 +1,747 @@
1
- <?php
2
- /**
3
- * Plugin Name: Google Analytics for WordPress by MonsterInsights
4
- * Plugin URI: https://www.monsterinsights.com/?utm_source=liteplugin&utm_medium=pluginheader&utm_campaign=pluginurl&utm_content=7%2E0%2E0
5
- * Description: The best Google Analytics plugin for WordPress. See how visitors find and use your website, so you can keep them coming back.
6
- * Author: MonsterInsights
7
- * Author URI: https://www.monsterinsights.com/?utm_source=liteplugin&utm_medium=pluginheader&utm_campaign=authoruri&utm_content=7%2E0%2E0
8
- *
9
- * Version: 7.7.1
10
- * Requires at least: 3.8.0
11
- * Tested up to: 5.1.1
12
- *
13
- * License: GPL v3
14
- *
15
- * Text Domain: google-analytics-for-wordpress
16
- * Domain Path: /languages
17
- *
18
- * MonsterInsights Lite
19
- * Copyright (C) 2008-2018, MonsterInsights, support@monsterinsights.com
20
- *
21
- * This program is free software: you can redistribute it and/or modify
22
- * it under the terms of the GNU General Public License as published by
23
- * the Free Software Foundation, either version 3 of the License, or
24
- * (at your option) any later version.
25
- *
26
- * This program is distributed in the hope that it will be useful,
27
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
- * GNU General Public License for more details.
30
- *
31
- * You should have received a copy of the GNU General Public License
32
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
33
- *
34
- * @category Plugin
35
- * @copyright Copyright © 2018 Chris Christoff
36
- * @author Chris Christoff
37
- * @package MonsterInsights
38
- */
39
-
40
- // Exit if accessed directly.
41
- if ( ! defined( 'ABSPATH' ) ) {
42
- exit;
43
- }
44
-
45
- /**
46
- * Main plugin class.
47
- *
48
- * @since 6.0.0
49
- *
50
- * @package MonsterInsights
51
- * @author Chris Christoff
52
- * @access public
53
- */
54
- final class MonsterInsights_Lite {
55
-
56
- /**
57
- * Holds the class object.
58
- *
59
- * @since 6.0.0
60
- * @access public
61
- * @var object Instance of instantiated MonsterInsights class.
62
- */
63
- public static $instance;
64
-
65
- /**
66
- * Plugin version, used for cache-busting of style and script file references.
67
- *
68
- * @since 6.0.0
69
- * @access public
70
- * @var string $version Plugin version.
71
- */
72
- public $version = '7.7.1';
73
-
74
- /**
75
- * Plugin file.
76
- *
77
- * @since 6.0.0
78
- * @access public
79
- * @var string $file PHP File constant for main file.
80
- */
81
- public $file;
82
-
83
- /**
84
- * The name of the plugin.
85
- *
86
- * @since 6.0.0
87
- * @access public
88
- * @var string $plugin_name Plugin name.
89
- */
90
- public $plugin_name = 'MonsterInsights Lite';
91
-
92
- /**
93
- * Unique plugin slug identifier.
94
- *
95
- * @since 6.0.0
96
- * @access public
97
- * @var string $plugin_slug Plugin slug.
98
- */
99
- public $plugin_slug = 'monsterinsights-lite';
100
-
101
- /**
102
- * Holds instance of MonsterInsights License class.
103
- *
104
- * @since 6.0.0
105
- * @access public
106
- * @var MonsterInsights_License $license Instance of License class.
107
- */
108
- protected $license;
109
-
110
- /**
111
- * Holds instance of MonsterInsights License Actions class.
112
- *
113
- * @since 6.0.0
114
- * @access public
115
- * @var MonsterInsights_License_Actions $license_actions Instance of License Actions class.
116
- */
117
- public $license_actions;
118
-
119
- /**
120
- * Holds instance of MonsterInsights Admin Notice class.
121
- *
122
- * @since 6.0.0
123
- * @access public
124
- * @var MonsterInsights_Admin_Notice $notices Instance of Admin Notice class.
125
- */
126
- public $notices;
127
-
128
- /**
129
- * Holds instance of MonsterInsights Reporting class.
130
- *
131
- * @since 6.0.0
132
- * @access public
133
- * @var MonsterInsights_Reporting $reporting Instance of Reporting class.
134
- */
135
- public $reporting;
136
-
137
- /**
138
- * Holds instance of MonsterInsights Auth class.
139
- *
140
- * @since 7.0.0
141
- * @access public
142
- * @var MonsterInsights_Auth $auth Instance of Auth class.
143
- */
144
- protected $auth;
145
-
146
- /**
147
- * Holds instance of MonsterInsights API Auth class.
148
- *
149
- * @since 6.0.0
150
- * @access public
151
- * @var MonsterInsights_Auth $api_auth Instance of APIAuth class.
152
- */
153
- public $api_auth;
154
-
155
- /**
156
- * Holds instance of MonsterInsights API Rest Routes class.
157
- *
158
- * @since 7.4.0
159
- * @access public
160
- * @var MonsterInsights_Rest_Routes $routes Instance of rest routes.
161
- */
162
- public $routes;
163
-
164
- /**
165
- * Primary class constructor.
166
- *
167
- * @since 6.0.0
168
- * @access public
169
- */
170
- public function __construct() {
171
- // We don't use this
172
- }
173
-
174
- /**
175
- * Returns the singleton instance of the class.
176
- *
177
- * @access public
178
- * @since 6.0.0
179
- *
180
- * @return object The MonsterInsights_Lite object.
181
- */
182
- public static function get_instance() {
183
-
184
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof MonsterInsights_Lite ) ) {
185
- self::$instance = new MonsterInsights_Lite();
186
- self::$instance->file = __FILE__;
187
-
188
- global $wp_version;
189
-
190
- // Detect non-supported WordPress version and return early
191
- if ( version_compare( $wp_version, '3.8', '<' ) && ( ! defined( 'MONSTERINSIGHTS_FORCE_ACTIVATION' ) || ! MONSTERINSIGHTS_FORCE_ACTIVATION ) ) {
192
- add_action( 'admin_notices', array( self::$instance, 'monsterinsights_wp_notice' ) );
193
- return;
194
- }
195
-
196
- // Detect Pro version and return early
197
- if ( defined( 'MONSTERINSIGHTS_PRO_VERSION' ) ) {
198
- add_action( 'admin_notices', array( self::$instance, 'monsterinsights_pro_notice' ) );
199
- return;
200
- }
201
-
202
- // Define constants
203
- self::$instance->define_globals();
204
-
205
- // Load in settings
206
- self::$instance->load_settings();
207
-
208
- // Load in Licensing
209
- self::$instance->load_licensing();
210
-
211
- // Load in Auth
212
- self::$instance->load_auth();
213
-
214
- // Load files
215
- self::$instance->require_files();
216
-
217
- // This does the version to version background upgrade routines and initial install
218
- $mi_version = get_option( 'monsterinsights_current_version', '5.5.3' );
219
- if ( version_compare( $mi_version, '7.6.0', '<' ) ) {
220
- monsterinsights_lite_call_install_and_upgrade();
221
- }
222
-
223
- if ( is_admin() ) {
224
- new AM_Notification( 'mi-lite', self::$instance->version );
225
- new AM_Deactivation_Survey( 'MonsterInsights', basename( dirname( __FILE__ ) ) );
226
- }
227
-
228
- // Load the plugin textdomain.
229
- add_action( 'plugins_loaded', array( self::$instance, 'load_plugin_textdomain' ) );
230
-
231
- // Load admin only components.
232
- if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
233
- self::$instance->notices = new MonsterInsights_Notice_Admin();
234
- self::$instance->license_actions = new MonsterInsights_License_Actions();
235
- self::$instance->reporting = new MonsterInsights_Reporting();
236
- self::$instance->api_auth = new MonsterInsights_API_Auth();
237
- if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
238
- self::$instance->require_updater();
239
- } else {
240
- add_action( 'admin_init', array( self::$instance, 'require_updater' ) );
241
- }
242
-
243
- self::$instance->routes = new MonsterInsights_Rest_Routes();
244
- }
245
-
246
- if ( monsterinsights_is_pro_version() ) {
247
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'pro/includes/load.php';
248
- } else {
249
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'lite/includes/load.php';
250
- }
251
-
252
- // Run hook to load MonsterInsights addons.
253
- do_action( 'monsterinsights_load_plugins' ); // the updater class for each addon needs to be instantiated via `monsterinsights_updater`
254
- }
255
-
256
- return self::$instance;
257
-
258
- }
259
-
260
- /**
261
- * Throw error on object clone
262
- *
263
- * The whole idea of the singleton design pattern is that there is a single
264
- * object therefore, we don't want the object to be cloned.
265
- *
266
- * @since 6.0.0
267
- * @access public
268
- *
269
- * @return void
270
- */
271
- public function __clone() {
272
- _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'google-analytics-for-wordpress' ), '6.0.0' );
273
- }
274
-
275
- /**
276
- * Disable unserializing of the class
277
- *
278
- * Attempting to wakeup an MonsterInsights instance will throw a doing it wrong notice.
279
- *
280
- * @since 6.0.0
281
- * @access public
282
- *
283
- * @return void
284
- */
285
- public function __wakeup() {
286
- _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'google-analytics-for-wordpress' ), '6.0.0' );
287
- }
288
-
289
- /**
290
- * Magic get function.
291
- *
292
- * We use this to lazy load certain functionality. Right now used to lazyload
293
- * the API & Auth frontend, so it's only loaded if user is using a plugin
294
- * that requires it.
295
- *
296
- * @since 7.0.0
297
- * @access public
298
- *
299
- * @return void
300
- */
301
- public function __get( $key ) {
302
- if ( $key === 'auth' ) {
303
- if ( empty( self::$instance->auth ) ) {
304
- // LazyLoad Auth for Frontend
305
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/auth.php';
306
- self::$instance->auth = new MonsterInsights_Auth();
307
- }
308
- return self::$instance->$key;
309
- } else if ( $key === 'license' ) {
310
- if ( empty( self::$instance->license ) ) {
311
- // LazyLoad Licensing for Frontend
312
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/license.php';
313
- self::$instance->license = new MonsterInsights_License();
314
- }
315
- return self::$instance->$key;
316
- } else {
317
- return self::$instance->$key;
318
- }
319
- }
320
-
321
- /**
322
- * Define MonsterInsights constants.
323
- *
324
- * This function defines all of the MonsterInsights PHP constants.
325
- *
326
- * @since 6.0.0
327
- * @access public
328
- *
329
- * @return void
330
- */
331
- public function define_globals() {
332
-
333
- if ( ! defined( 'MONSTERINSIGHTS_VERSION' ) ) {
334
- define( 'MONSTERINSIGHTS_VERSION', $this->version );
335
- }
336
-
337
- if ( ! defined( 'MONSTERINSIGHTS_LITE_VERSION' ) ) {
338
- define( 'MONSTERINSIGHTS_LITE_VERSION', MONSTERINSIGHTS_VERSION );
339
- }
340
-
341
- if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_NAME' ) ) {
342
- define( 'MONSTERINSIGHTS_PLUGIN_NAME', $this->plugin_name );
343
- }
344
-
345
- if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_SLUG' ) ) {
346
- define( 'MONSTERINSIGHTS_PLUGIN_SLUG', $this->plugin_slug );
347
- }
348
-
349
- if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_FILE' ) ) {
350
- define( 'MONSTERINSIGHTS_PLUGIN_FILE', $this->file );
351
- }
352
-
353
- if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_DIR' ) ) {
354
- define( 'MONSTERINSIGHTS_PLUGIN_DIR', plugin_dir_path( $this->file ) );
355
- }
356
-
357
- if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_URL' ) ) {
358
- define( 'MONSTERINSIGHTS_PLUGIN_URL', plugin_dir_url( $this->file ) );
359
- }
360
- }
361
-
362
- /**
363
- * Loads the plugin textdomain for translation.
364
- *
365
- * @access public
366
- * @since 6.0.0
367
- *
368
- * @return void
369
- */
370
- public function load_plugin_textdomain() {
371
-
372
- $mi_locale = get_locale();
373
- if ( function_exists( 'get_user_locale' ) ) {
374
- $mi_locale = get_user_locale();
375
- }
376
-
377
- // Traditional WordPress plugin locale filter.
378
- $mi_locale = apply_filters( 'plugin_locale', $mi_locale, 'google-analytics-for-wordpress' );
379
- $mi_mofile = sprintf( '%1$s-%2$s.mo', 'google-analytics-for-wordpress', $mi_locale );
380
-
381
- // Look for wp-content/languages/google-analytics-for-wordpress/google-analytics-for-wordpress-{lang}_{country}.mo
382
- $mi_mofile1 = WP_LANG_DIR . '/google-analytics-for-wordpress/' . $mi_mofile;
383
-
384
- // Look in wp-content/languages/plugins/google-analytics-for-wordpress/google-analytics-for-wordpress-{lang}_{country}.mo
385
- $mi_mofile2 = WP_LANG_DIR . '/plugins/google-analytics-for-wordpress/' . $mi_mofile;
386
-
387
- // Look in wp-content/languages/plugins/google-analytics-for-wordpress-{lang}_{country}.mo
388
- $mi_mofile3 = WP_LANG_DIR . '/plugins/' . $mi_mofile;
389
-
390
- // Look in wp-content/plugins/google-analytics-for-wordpress/languages/google-analytics-for-wordpress-{lang}_{country}.mo
391
- $mi_mofile4 = dirname( plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ) ) . '/languages/';
392
- $mi_mofile4 = apply_filters( 'monsterinsights_lite_languages_directory', $mi_mofile4 );
393
-
394
- if ( file_exists( $mi_mofile1 ) ) {
395
- load_textdomain( 'google-analytics-for-wordpress', $mi_mofile1 );
396
- } elseif ( file_exists( $mi_mofile2 ) ) {
397
- load_textdomain( 'google-analytics-for-wordpress', $mi_mofile2 );
398
- } elseif ( file_exists( $mi_mofile3 ) ) {
399
- load_textdomain( 'google-analytics-for-wordpress', $mi_mofile3 );
400
- } else {
401
- load_plugin_textdomain( 'google-analytics-for-wordpress', false, $mi_mofile4 );
402
- }
403
-
404
- }
405
-
406
- /**
407
- * Output a nag notice if the user has an out of date WP version installed
408
- *
409
- * @access public
410
- * @since 6.0.0
411
- *
412
- * @return void
413
- */
414
- public function monsterinsights_wp_notice() {
415
- $url = admin_url( 'plugins.php' );
416
- // Check for MS dashboard
417
- if( is_network_admin() ) {
418
- $url = network_admin_url( 'plugins.php' );
419
- }
420
- ?>
421
- <div class="error">
422
- <p><?php echo sprintf( esc_html__( 'Sorry, but your version of WordPress does not meet MonsterInsights\'s required version of %1$s3.8%2$s to run properly. The plugin not been activated. %3$sClick here to return to the Dashboard%4$s.', 'google-analytics-for-wordpress' ), '<strong>', '</strong>', '<a href="' . $url . '">', '</a>' ); ?></p>
423
- </div>
424
- <?php
425
- }
426
-
427
- /**
428
- * Output a nag notice if the user has both Lite and Pro activated
429
- *
430
- * @access public
431
- * @since 6.0.0
432
- *
433
- * @return void
434
- */
435
- public function monsterinsights_pro_notice() {
436
- $url = admin_url( 'plugins.php' );
437
- // Check for MS dashboard
438
- if( is_network_admin() ) {
439
- $url = network_admin_url( 'plugins.php' );
440
- }
441
- ?>
442
- <div class="error">
443
- <p><?php echo sprintf( esc_html__( 'Please %1$suninstall%2$s the MonsterInsights Lite Plugin. Your Pro version of MonsterInsights may not work as expected until the Lite version is uninstalled.', 'google-analytics-for-wordpress' ), '<a href="' . $url . '">', '</a>' ); ?></p>
444
- </div>
445
- <?php
446
-
447
- }
448
-
449
- /**
450
- * Loads MonsterInsights settings
451
- *
452
- * Adds the items to the base object, and adds the helper functions.
453
- *
454
- * @since 6.0.0
455
- * @access public
456
- *
457
- * @return void
458
- */
459
- public function load_settings() {
460
- global $monsterinsights_settings;
461
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/options.php';
462
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/helpers.php';
463
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/deprecated.php';
464
- $monsterinsights_settings = monsterinsights_get_options();
465
- }
466
-
467
-
468
- /**
469
- * Loads MonsterInsights License
470
- *
471
- * Loads license class used by MonsterInsights
472
- *
473
- * @since 7.0.0
474
- * @access public
475
- *
476
- * @return void
477
- */
478
- public function load_licensing(){
479
- if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
480
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/license.php';
481
- self::$instance->license = new MonsterInsights_License();
482
- }
483
- }
484
-
485
- /**
486
- * Loads MonsterInsights Auth
487
- *
488
- * Loads auth used by MonsterInsights
489
- *
490
- * @since 7.0.0
491
- * @access public
492
- *
493
- * @return void
494
- */
495
- public function load_auth() {
496
- if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
497
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/auth.php';
498
- self::$instance->auth = new MonsterInsights_Auth();
499
- }
500
- }
501
-
502
- /**
503
- * Loads all files into scope.
504
- *
505
- * @access public
506
- * @since 6.0.0
507
- *
508
- * @return void
509
- */
510
- public function require_files() {
511
-
512
- if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
513
-
514
- // Lite and Pro files
515
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'assets/lib/pandora/class-am-notification.php';
516
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'assets/lib/pandora/class-am-deactivation-survey.php';
517
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'assets/lib/pandora/class-am-dashboard-widget-extend-feed.php';
518
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/ajax.php';
519
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/admin.php';
520
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/common.php';
521
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/notice.php';
522
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/capabilities.php';
523
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/licensing/license-actions.php';
524
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/licensing/autoupdate.php';
525
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/review.php';
526
-
527
- // Pages
528
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/settings.php';
529
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/tools.php';
530
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/reports.php';
531
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/addons.php';
532
-
533
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/api-auth.php';
534
-
535
- // Reports
536
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/reports/abstract-report.php';
537
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/reports/overview.php';
538
-
539
- // Reporting Functionality
540
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/reporting.php';
541
-
542
- // Routes used by Vue
543
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/routes.php';
544
- }
545
-
546
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/api-request.php';
547
-
548
- if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
549
- // Late loading classes (self instantiating)
550
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/tracking.php';
551
- }
552
-
553
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/frontend/frontend.php';
554
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/frontend/seedprod.php';
555
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/measurement-protocol.php';
556
- }
557
-
558
- /**
559
- * Loads all updater related files and functions into scope.
560
- *
561
- * @access public
562
- * @since 6.0.0
563
- *
564
- * @return null Return early if the license key is not set or there are key errors.
565
- */
566
- public function require_updater() {
567
-
568
- // Retrieve the license key. If it is not set or if there are issues, return early.
569
- $key = self::$instance->license->get_valid_license_key();
570
- if ( ! $key ) {
571
- return;
572
- }
573
-
574
- // Load the updater class.
575
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/licensing/updater.php';
576
-
577
- // Fire a hook for Addons to register their updater since we know the key is present.
578
- do_action( 'monsterinsights_updater', $key );
579
- }
580
- }
581
-
582
- /**
583
- * Fired when the plugin is activated.
584
- *
585
- * @access public
586
- * @since 6.0.0
587
- *
588
- * @global int $wp_version The version of WordPress for this install.
589
- * @global object $wpdb The WordPress database object.
590
- * @param boolean $network_wide True if WPMU superadmin uses "Network Activate" action, false otherwise.
591
- *
592
- * @return void
593
- */
594
- function monsterinsights_lite_activation_hook( $network_wide ) {
595
-
596
- global $wp_version;
597
-
598
- $url = admin_url( 'plugins.php' );
599
- // Check for MS dashboard
600
- if ( is_network_admin() ) {
601
- $url = network_admin_url( 'plugins.php' );
602
- }
603
-
604
- if ( version_compare( $wp_version, '3.8', '<' ) && ( ! defined( 'MONSTERINSIGHTS_FORCE_ACTIVATION' ) || ! MONSTERINSIGHTS_FORCE_ACTIVATION ) ) {
605
- deactivate_plugins( plugin_basename( __FILE__ ) );
606
- wp_die( sprintf( esc_html__( 'Sorry, but your version of WordPress does not meet MonsterInsight\'s required version of %1$s3.8%2$s to run properly. The plugin not been activated. %3$sClick here to return to the Dashboard%4$s.', 'google-analytics-by-wordpress' ), '<strong>', '</strong>', '<a href="' . $url . '">', '</a>' ) );
607
- }
608
-
609
- if ( class_exists( 'MonsterInsights' ) ) {
610
- deactivate_plugins( plugin_basename( __FILE__ ) );
611
- wp_die( sprintf( esc_html__( 'Please uninstall and remove MonsterInsights Pro before activating Google Analytics for WordPress by MonsterInsights. The Lite version has not been activated. %1$sClick here to return to the Dashboard%2$s.', 'google-analytics-by-wordpress' ), '<a href="' . $url . '">', '</a>' ) );
612
- }
613
-
614
- // Add transient to trigger redirect.
615
- set_transient( '_monsterinsights_activation_redirect', 1, 30 );
616
- }
617
- register_activation_hook( __FILE__, 'monsterinsights_lite_activation_hook' );
618
-
619
- /**
620
- * Fired when the plugin is uninstalled.
621
- *
622
- * @access public
623
- * @since 6.0.0
624
- *
625
- * @return void
626
- */
627
- function monsterinsights_lite_uninstall_hook() {
628
- wp_cache_flush();
629
-
630
- // Note, if both MI Pro and Lite are active, this is an MI Pro instance
631
- // Therefore MI Lite can only use functions of the instance common to
632
- // both plugins. If it needs to be pro specific, then include a file that
633
- // has that method.
634
- $instance = MonsterInsights();
635
-
636
- // If uninstalling via wp-cli load admin-specific files only here.
637
- if ( defined( 'WP_CLI' ) && WP_CLI ) {
638
- define( 'WP_ADMIN', true );
639
- $instance->require_files();
640
- $instance->load_auth();
641
- $instance->load_licensing();
642
- $instance->notices = new MonsterInsights_Notice_Admin();
643
- $instance->license_actions = new MonsterInsights_License_Actions();
644
- $instance->reporting = new MonsterInsights_Reporting();
645
- $instance->api_auth = new MonsterInsights_API_Auth();
646
- }
647
-
648
- // Don't delete any data if the PRO version is already active.
649
- if ( monsterinsights_is_pro_version() ) {
650
- return;
651
- }
652
-
653
- if ( is_multisite() ) {
654
- $site_list = get_sites();
655
- foreach ( (array) $site_list as $site ) {
656
- switch_to_blog( $site->blog_id );
657
-
658
- // Delete auth
659
- $instance->api_auth->delete_auth();
660
-
661
- // Delete data
662
- $instance->reporting->delete_aggregate_data('site');
663
-
664
- // Delete license
665
- $instance->license->delete_site_license();
666
-
667
- restore_current_blog();
668
- }
669
- // Delete network auth using a custom function as some variables are not initiated.
670
- $instance->api_auth->uninstall_network_auth();
671
-
672
- // Delete network data
673
- $instance->reporting->delete_aggregate_data('network');
674
-
675
- // Delete network license
676
- $instance->license->delete_network_license();
677
- } else {
678
- // Delete auth
679
- $instance->api_auth->delete_auth();
680
-
681
- // Delete data
682
- $instance->reporting->delete_aggregate_data('site');
683
-
684
- // Delete license
685
- $instance->license->delete_site_license();
686
- }
687
-
688
- }
689
- register_uninstall_hook( __FILE__, 'monsterinsights_lite_uninstall_hook' );
690
-
691
- /**
692
- * The main function responsible for returning the one true MonsterInsights_Lite
693
- * Instance to functions everywhere.
694
- *
695
- * Use this function like you would a global variable, except without needing
696
- * to declare the global.
697
- *
698
- * Example: <?php $monsterinsights = MonsterInsights_Lite(); ?>
699
- *
700
- * @since 6.0.0
701
- *
702
- * @uses MonsterInsights_Lite::get_instance() Retrieve MonsterInsights_Lite instance.
703
- *
704
- * @return MonsterInsights_Lite The singleton MonsterInsights_Lite instance.
705
- */
706
- function MonsterInsights_Lite() {
707
- return MonsterInsights_Lite::get_instance();
708
- }
709
-
710
- /**
711
- * MonsterInsights Install and Updates.
712
- *
713
- * This function is used install and upgrade MonsterInsights. This is used for upgrade routines
714
- * that can be done automatically, behind the scenes without the need for user interaction
715
- * (for example pagination or user input required), as well as the initial install.
716
- *
717
- * @since 6.0.0
718
- * @access public
719
- *
720
- * @global string $wp_version WordPress version (provided by WordPress core).
721
- * @uses MonsterInsights_Lite::load_settings() Loads MonsterInsights settings
722
- * @uses MonsterInsights_Install::init() Runs upgrade process
723
- *
724
- * @return void
725
- */
726
- function monsterinsights_lite_install_and_upgrade() {
727
- global $wp_version;
728
-
729
- // If the WordPress site doesn't meet the correct WP version requirements, don't activate MonsterInsights
730
- if ( version_compare( $wp_version, '3.8', '<' ) ) {
731
- if ( is_plugin_active( plugin_basename( __FILE__ ) ) ) {
732
- return;
733
- }
734
- }
735
-
736
- // Don't run if MI Pro is installed
737
- if ( class_exists( 'MonsterInsights' ) ) {
738
- if ( is_plugin_active( plugin_basename( __FILE__ ) ) ) {
739
- return;
740
- }
741
- }
742
-
743
-
744
- // Load settings and globals (so we can use/set them during the upgrade process)
745
- MonsterInsights_Lite()->define_globals();
746
- MonsterInsights_Lite()->load_settings();
747
-
748
- // Load in Licensing
749
- MonsterInsights()->load_licensing();
750
-
751
- // Load in Auth
752
- MonsterInsights()->load_auth();
753
-
754
- // Load upgrade file
755
- require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/install.php';
756
-
757
- // Run the MonsterInsights upgrade routines
758
- $updates = new MonsterInsights_Install();
759
- $updates->init();
760
- }
761
-
762
- /**
763
- * MonsterInsights check for install and update processes.
764
- *
765
- * This function is used to call the MonsterInsights automatic upgrade class, which in turn
766
- * checks to see if there are any update procedures to be run, and if
767
- * so runs them. Also installs MonsterInsights for the first time.
768
- *
769
- * @since 6.0.0
770
- * @access public
771
- *
772
- * @uses MonsterInsights_Install() Runs install and upgrade process.
773
- *
774
- * @return void
775
- */
776
- function monsterinsights_lite_call_install_and_upgrade(){
777
- add_action( 'wp_loaded', 'monsterinsights_lite_install_and_upgrade' );
778
- }
779
-
780
- /**
781
- * Returns the MonsterInsights combined object that you can use for both
782
- * MonsterInsights Lite and Pro Users. When both plugins active, defers to the
783
- * more complete Pro object.
784
- *
785
- * Warning: Do not use this in Lite or Pro specific code (use the individual objects instead).
786
- * Also do not use in the MonsterInsights Lite/Pro upgrade and install routines.
787
- *
788
- * Use this function like you would a global variable, except without needing
789
- * to declare the global.
790
- *
791
- * Prevents the need to do conditional global object logic when you have code that you want to work with
792
- * both Pro and Lite.
793
- *
794
- * Example: <?php $monsterinsights = MonsterInsights(); ?>
795
- *
796
- * @since 6.0.0
797
- *
798
- * @uses MonsterInsights::get_instance() Retrieve MonsterInsights Pro instance.
799
- * @uses MonsterInsights_Lite::get_instance() Retrieve MonsterInsights Lite instance.
800
- *
801
- * @return MonsterInsights The singleton MonsterInsights instance.
802
- */
803
- if ( ! function_exists( 'MonsterInsights' ) ) {
804
- function MonsterInsights() {
805
- return ( class_exists( 'MonsterInsights' ) ? MonsterInsights_Pro() : MonsterInsights_Lite() );
806
- }
807
- add_action( 'plugins_loaded', 'MonsterInsights' );
808
- }
1
+ <?php
2
+ /**
3
+ * Plugin Name: Google Analytics for WordPress by MonsterInsights
4
+ * Plugin URI: https://www.monsterinsights.com/?utm_source=liteplugin&utm_medium=pluginheader&utm_campaign=pluginurl&utm_content=7%2E0%2E0
5
+ * Description: The best Google Analytics plugin for WordPress. See how visitors find and use your website, so you can keep them coming back.
6
+ * Author: MonsterInsights
7
+ * Author URI: https://www.monsterinsights.com/?utm_source=liteplugin&utm_medium=pluginheader&utm_campaign=authoruri&utm_content=7%2E0%2E0
8
+ *
9
+ * Version: 7.8.0
10
+ * Requires at least: 3.8.0
11
+ * Tested up to: 5.1.1
12
+ *
13
+ * License: GPL v3
14
+ *
15
+ * Text Domain: google-analytics-for-wordpress
16
+ * Domain Path: /languages
17
+ *
18
+ * MonsterInsights Lite
19
+ * Copyright (C) 2008-2018, MonsterInsights, support@monsterinsights.com
20
+ *
21
+ * This program is free software: you can redistribute it and/or modify
22
+ * it under the terms of the GNU General Public License as published by
23
+ * the Free Software Foundation, either version 3 of the License, or
24
+ * (at your option) any later version.
25
+ *
26
+ * This program is distributed in the hope that it will be useful,
27
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
+ * GNU General Public License for more details.
30
+ *
31
+ * You should have received a copy of the GNU General Public License
32
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
33
+ *
34
+ * @category Plugin
35
+ * @copyright Copyright © 2018 Chris Christoff
36
+ * @author Chris Christoff
37
+ * @package MonsterInsights
38
+ */
39
+
40
+ // Exit if accessed directly.
41
+ if ( ! defined( 'ABSPATH' ) ) {
42
+ exit;
43
+ }
44
+
45
+ /**
46
+ * Main plugin class.
47
+ *
48
+ * @since 6.0.0
49
+ *
50
+ * @package MonsterInsights
51
+ * @author Chris Christoff
52
+ * @access public
53
+ */
54
+ final class MonsterInsights_Lite {
55
+
56
+ /**
57
+ * Holds the class object.
58
+ *
59
+ * @since 6.0.0
60
+ * @access public
61
+ * @var object Instance of instantiated MonsterInsights class.
62
+ */
63
+ public static $instance;
64
+
65
+ /**
66
+ * Plugin version, used for cache-busting of style and script file references.
67
+ *
68
+ * @since 6.0.0
69
+ * @access public
70
+ * @var string $version Plugin version.
71
+ */
72
+ public $version = '7.8.0';
73
+
74
+ /**
75
+ * Plugin file.
76
+ *
77
+ * @since 6.0.0
78
+ * @access public
79
+ * @var string $file PHP File constant for main file.
80
+ */
81
+ public $file;
82
+
83
+ /**
84
+ * The name of the plugin.
85
+ *
86
+ * @since 6.0.0
87
+ * @access public
88
+ * @var string $plugin_name Plugin name.
89
+ */
90
+ public $plugin_name = 'MonsterInsights Lite';
91
+
92
+ /**
93
+ * Unique plugin slug identifier.
94
+ *
95
+ * @since 6.0.0
96
+ * @access public
97
+ * @var string $plugin_slug Plugin slug.
98
+ */
99
+ public $plugin_slug = 'monsterinsights-lite';
100
+
101
+ /**
102
+ * Holds instance of MonsterInsights License class.
103
+ *
104
+ * @since 6.0.0
105
+ * @access public
106
+ * @var MonsterInsights_License $license Instance of License class.
107
+ */
108
+ protected $license;
109
+
110
+ /**
111
+ * Holds instance of MonsterInsights Admin Notice class.
112
+ *
113
+ * @since 6.0.0
114
+ * @access public
115
+ * @var MonsterInsights_Admin_Notice $notices Instance of Admin Notice class.
116
+ */
117
+ public $notices;
118
+
119
+ /**
120
+ * Holds instance of MonsterInsights Reporting class.
121
+ *
122
+ * @since 6.0.0
123
+ * @access public
124
+ * @var MonsterInsights_Reporting $reporting Instance of Reporting class.
125
+ */
126
+ public $reporting;
127
+
128
+ /**
129
+ * Holds instance of MonsterInsights Auth class.
130
+ *
131
+ * @since 7.0.0
132
+ * @access public
133
+ * @var MonsterInsights_Auth $auth Instance of Auth class.
134
+ */
135
+ protected $auth;
136
+
137
+ /**
138
+ * Holds instance of MonsterInsights API Auth class.
139
+ *
140
+ * @since 6.0.0
141
+ * @access public
142
+ * @var MonsterInsights_Auth $api_auth Instance of APIAuth class.
143
+ */
144
+ public $api_auth;
145
+
146
+ /**
147
+ * Holds instance of MonsterInsights API Rest Routes class.
148
+ *
149
+ * @since 7.4.0
150
+ * @access public
151
+ * @var MonsterInsights_Rest_Routes $routes Instance of rest routes.
152
+ */
153
+ public $routes;
154
+
155
+ /**
156
+ * Primary class constructor.
157
+ *
158
+ * @since 6.0.0
159
+ * @access public
160
+ */
161
+ public function __construct() {
162
+ // We don't use this
163
+ }
164
+
165
+ /**
166
+ * Returns the singleton instance of the class.
167
+ *
168
+ * @access public
169
+ * @since 6.0.0
170
+ *
171
+ * @return object The MonsterInsights_Lite object.
172
+ */
173
+ public static function get_instance() {
174
+
175
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof MonsterInsights_Lite ) ) {
176
+ self::$instance = new MonsterInsights_Lite();
177
+ self::$instance->file = __FILE__;
178
+
179
+ global $wp_version;
180
+
181
+ // Detect non-supported WordPress version and return early
182
+ if ( version_compare( $wp_version, '3.8', '<' ) && ( ! defined( 'MONSTERINSIGHTS_FORCE_ACTIVATION' ) || ! MONSTERINSIGHTS_FORCE_ACTIVATION ) ) {
183
+ add_action( 'admin_notices', array( self::$instance, 'monsterinsights_wp_notice' ) );
184
+ return;
185
+ }
186
+
187
+ // Detect Pro version and return early
188
+ if ( defined( 'MONSTERINSIGHTS_PRO_VERSION' ) ) {
189
+ add_action( 'admin_notices', array( self::$instance, 'monsterinsights_pro_notice' ) );
190
+ return;
191
+ }
192
+
193
+ // Define constants
194
+ self::$instance->define_globals();
195
+
196
+ // Load in settings
197
+ self::$instance->load_settings();
198
+
199
+ // Load in Licensing
200
+ self::$instance->load_licensing();
201
+
202
+ // Load in Auth
203
+ self::$instance->load_auth();
204
+
205
+ // Load files
206
+ self::$instance->require_files();
207
+
208
+ // This does the version to version background upgrade routines and initial install
209
+ $mi_version = get_option( 'monsterinsights_current_version', '5.5.3' );
210
+ if ( version_compare( $mi_version, '7.6.0', '<' ) ) {
211
+ monsterinsights_lite_call_install_and_upgrade();
212
+ }
213
+
214
+ if ( is_admin() ) {
215
+ new AM_Notification( 'mi-lite', self::$instance->version );
216
+ new AM_Deactivation_Survey( 'MonsterInsights', basename( dirname( __FILE__ ) ) );
217
+ }
218
+
219
+ // Load the plugin textdomain.
220
+ add_action( 'plugins_loaded', array( self::$instance, 'load_plugin_textdomain' ) );
221
+
222
+ // Load admin only components.
223
+ if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
224
+ self::$instance->notices = new MonsterInsights_Notice_Admin();
225
+ self::$instance->reporting = new MonsterInsights_Reporting();
226
+ self::$instance->api_auth = new MonsterInsights_API_Auth();
227
+ self::$instance->routes = new MonsterInsights_Rest_Routes();
228
+ }
229
+
230
+ if ( monsterinsights_is_pro_version() ) {
231
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'pro/includes/load.php';
232
+ } else {
233
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'lite/includes/load.php';
234
+ }
235
+
236
+ // Run hook to load MonsterInsights addons.
237
+ do_action( 'monsterinsights_load_plugins' ); // the updater class for each addon needs to be instantiated via `monsterinsights_updater`
238
+ }
239
+
240
+ return self::$instance;
241
+
242
+ }
243
+
244
+ /**
245
+ * Throw error on object clone
246
+ *
247
+ * The whole idea of the singleton design pattern is that there is a single
248
+ * object therefore, we don't want the object to be cloned.
249
+ *
250
+ * @since 6.0.0
251
+ * @access public
252
+ *
253
+ * @return void
254
+ */
255
+ public function __clone() {
256
+ _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'google-analytics-for-wordpress' ), '6.0.0' );
257
+ }
258
+
259
+ /**
260
+ * Disable unserializing of the class
261
+ *
262
+ * Attempting to wakeup an MonsterInsights instance will throw a doing it wrong notice.
263
+ *
264
+ * @since 6.0.0
265
+ * @access public
266
+ *
267
+ * @return void
268
+ */
269
+ public function __wakeup() {
270
+ _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'google-analytics-for-wordpress' ), '6.0.0' );
271
+ }
272
+
273
+ /**
274
+ * Magic get function.
275
+ *
276
+ * We use this to lazy load certain functionality. Right now used to lazyload
277
+ * the API & Auth frontend, so it's only loaded if user is using a plugin
278
+ * that requires it.
279
+ *
280
+ * @since 7.0.0
281
+ * @access public
282
+ *
283
+ * @return void
284
+ */
285
+ public function __get( $key ) {
286
+ if ( $key === 'auth' ) {
287
+ if ( empty( self::$instance->auth ) ) {
288
+ // LazyLoad Auth for Frontend
289
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/auth.php';
290
+ self::$instance->auth = new MonsterInsights_Auth();
291
+ }
292
+ return self::$instance->$key;
293
+ } else {
294
+ return self::$instance->$key;
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Define MonsterInsights constants.
300
+ *
301
+ * This function defines all of the MonsterInsights PHP constants.
302
+ *
303
+ * @since 6.0.0
304
+ * @access public
305
+ *
306
+ * @return void
307
+ */
308
+ public function define_globals() {
309
+
310
+ if ( ! defined( 'MONSTERINSIGHTS_VERSION' ) ) {
311
+ define( 'MONSTERINSIGHTS_VERSION', $this->version );
312
+ }
313
+
314
+ if ( ! defined( 'MONSTERINSIGHTS_LITE_VERSION' ) ) {
315
+ define( 'MONSTERINSIGHTS_LITE_VERSION', MONSTERINSIGHTS_VERSION );
316
+ }
317
+
318
+ if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_NAME' ) ) {
319
+ define( 'MONSTERINSIGHTS_PLUGIN_NAME', $this->plugin_name );
320
+ }
321
+
322
+ if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_SLUG' ) ) {
323
+ define( 'MONSTERINSIGHTS_PLUGIN_SLUG', $this->plugin_slug );
324
+ }
325
+
326
+ if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_FILE' ) ) {
327
+ define( 'MONSTERINSIGHTS_PLUGIN_FILE', $this->file );
328
+ }
329
+
330
+ if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_DIR' ) ) {
331
+ define( 'MONSTERINSIGHTS_PLUGIN_DIR', plugin_dir_path( $this->file ) );
332
+ }
333
+
334
+ if ( ! defined( 'MONSTERINSIGHTS_PLUGIN_URL' ) ) {
335
+ define( 'MONSTERINSIGHTS_PLUGIN_URL', plugin_dir_url( $this->file ) );
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Loads the plugin textdomain for translation.
341
+ *
342
+ * @access public
343
+ * @since 6.0.0
344
+ *
345
+ * @return void
346
+ */
347
+ public function load_plugin_textdomain() {
348
+
349
+ $mi_locale = get_locale();
350
+ if ( function_exists( 'get_user_locale' ) ) {
351
+ $mi_locale = get_user_locale();
352
+ }
353
+
354
+ // Traditional WordPress plugin locale filter.
355
+ $mi_locale = apply_filters( 'plugin_locale', $mi_locale, 'google-analytics-for-wordpress' );
356
+ $mi_mofile = sprintf( '%1$s-%2$s.mo', 'google-analytics-for-wordpress', $mi_locale );
357
+
358
+ // Look for wp-content/languages/google-analytics-for-wordpress/google-analytics-for-wordpress-{lang}_{country}.mo
359
+ $mi_mofile1 = WP_LANG_DIR . '/google-analytics-for-wordpress/' . $mi_mofile;
360
+
361
+ // Look in wp-content/languages/plugins/google-analytics-for-wordpress/google-analytics-for-wordpress-{lang}_{country}.mo
362
+ $mi_mofile2 = WP_LANG_DIR . '/plugins/google-analytics-for-wordpress/' . $mi_mofile;
363
+
364
+ // Look in wp-content/languages/plugins/google-analytics-for-wordpress-{lang}_{country}.mo
365
+ $mi_mofile3 = WP_LANG_DIR . '/plugins/' . $mi_mofile;
366
+
367
+ // Look in wp-content/plugins/google-analytics-for-wordpress/languages/google-analytics-for-wordpress-{lang}_{country}.mo
368
+ $mi_mofile4 = dirname( plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ) ) . '/languages/';
369
+ $mi_mofile4 = apply_filters( 'monsterinsights_lite_languages_directory', $mi_mofile4 );
370
+
371
+ if ( file_exists( $mi_mofile1 ) ) {
372
+ load_textdomain( 'google-analytics-for-wordpress', $mi_mofile1 );
373
+ } elseif ( file_exists( $mi_mofile2 ) ) {
374
+ load_textdomain( 'google-analytics-for-wordpress', $mi_mofile2 );
375
+ } elseif ( file_exists( $mi_mofile3 ) ) {
376
+ load_textdomain( 'google-analytics-for-wordpress', $mi_mofile3 );
377
+ } else {
378
+ load_plugin_textdomain( 'google-analytics-for-wordpress', false, $mi_mofile4 );
379
+ }
380
+
381
+ }
382
+
383
+ /**
384
+ * Output a nag notice if the user has an out of date WP version installed
385
+ *
386
+ * @access public
387
+ * @since 6.0.0
388
+ *
389
+ * @return void
390
+ */
391
+ public function monsterinsights_wp_notice() {
392
+ $url = admin_url( 'plugins.php' );
393
+ // Check for MS dashboard
394
+ if( is_network_admin() ) {
395
+ $url = network_admin_url( 'plugins.php' );
396
+ }
397
+ ?>
398
+ <div class="error">
399
+ <p><?php echo sprintf( esc_html__( 'Sorry, but your version of WordPress does not meet MonsterInsights\'s required version of %1$s3.8%2$s to run properly. The plugin not been activated. %3$sClick here to return to the Dashboard%4$s.', 'google-analytics-for-wordpress' ), '<strong>', '</strong>', '<a href="' . $url . '">', '</a>' ); ?></p>
400
+ </div>
401
+ <?php
402
+ }
403
+
404
+ /**
405
+ * Output a nag notice if the user has both Lite and Pro activated
406
+ *
407
+ * @access public
408
+ * @since 6.0.0
409
+ *
410
+ * @return void
411
+ */
412
+ public function monsterinsights_pro_notice() {
413
+ $url = admin_url( 'plugins.php' );
414
+ // Check for MS dashboard
415
+ if( is_network_admin() ) {
416
+ $url = network_admin_url( 'plugins.php' );
417
+ }
418
+ ?>
419
+ <div class="error">
420
+ <p><?php echo sprintf( esc_html__( 'Please %1$suninstall%2$s the MonsterInsights Lite Plugin. Your Pro version of MonsterInsights may not work as expected until the Lite version is uninstalled.', 'google-analytics-for-wordpress' ), '<a href="' . $url . '">', '</a>' ); ?></p>
421
+ </div>
422
+ <?php
423
+
424
+ }
425
+
426
+ /**
427
+ * Loads MonsterInsights settings
428
+ *
429
+ * Adds the items to the base object, and adds the helper functions.
430
+ *
431
+ * @since 6.0.0
432
+ * @access public
433
+ *
434
+ * @return void
435
+ */
436
+ public function load_settings() {
437
+ global $monsterinsights_settings;
438
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/options.php';
439
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/helpers.php';
440
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/deprecated.php';
441
+ $monsterinsights_settings = monsterinsights_get_options();
442
+ }
443
+
444
+
445
+ /**
446
+ * Loads MonsterInsights License
447
+ *
448
+ * Loads license class used by MonsterInsights
449
+ *
450
+ * @since 7.0.0
451
+ * @access public
452
+ *
453
+ * @return void
454
+ */
455
+ public function load_licensing(){
456
+ if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
457
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'lite/includes/license-compat.php';
458
+ self::$instance->license = new MonsterInsights_License_Compat();
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Loads MonsterInsights Auth
464
+ *
465
+ * Loads auth used by MonsterInsights
466
+ *
467
+ * @since 7.0.0
468
+ * @access public
469
+ *
470
+ * @return void
471
+ */
472
+ public function load_auth() {
473
+ if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
474
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/auth.php';
475
+ self::$instance->auth = new MonsterInsights_Auth();
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Loads all files into scope.
481
+ *
482
+ * @access public
483
+ * @since 6.0.0
484
+ *
485
+ * @return void
486
+ */
487
+ public function require_files() {
488
+
489
+ if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
490
+
491
+ // Lite and Pro files
492
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'assets/lib/pandora/class-am-notification.php';
493
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'assets/lib/pandora/class-am-deactivation-survey.php';
494
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'assets/lib/pandora/class-am-dashboard-widget-extend-feed.php';
495
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/ajax.php';
496
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/admin.php';
497
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/common.php';
498
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/notice.php';
499
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/capabilities.php';
500
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/licensing/autoupdate.php';
501
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/review.php';
502
+
503
+ // Pages
504
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/settings.php';
505
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/tools.php';
506
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/reports.php';
507
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/pages/addons.php';
508
+
509
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/api-auth.php';
510
+
511
+ // Reports
512
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/reports/abstract-report.php';
513
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/reports/overview.php';
514
+
515
+ // Reporting Functionality
516
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/reporting.php';
517
+
518
+ // Routes used by Vue
519
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/routes.php';
520
+ }
521
+
522
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/api-request.php';
523
+
524
+ if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
525
+ // Late loading classes (self instantiating)
526
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/admin/tracking.php';
527
+ }
528
+
529
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/frontend/frontend.php';
530
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/frontend/seedprod.php';
531
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/measurement-protocol.php';
532
+ }
533
+ }
534
+
535
+ /**
536
+ * Fired when the plugin is activated.
537
+ *
538
+ * @access public
539
+ * @since 6.0.0
540
+ *
541
+ * @global int $wp_version The version of WordPress for this install.
542
+ * @global object $wpdb The WordPress database object.
543
+ * @param boolean $network_wide True if WPMU superadmin uses "Network Activate" action, false otherwise.
544
+ *
545
+ * @return void
546
+ */
547
+ function monsterinsights_lite_activation_hook( $network_wide ) {
548
+
549
+ global $wp_version;
550
+
551
+ $url = admin_url( 'plugins.php' );
552
+ // Check for MS dashboard
553
+ if ( is_network_admin() ) {
554
+ $url = network_admin_url( 'plugins.php' );
555
+ }
556
+
557
+ if ( version_compare( $wp_version, '3.8', '<' ) && ( ! defined( 'MONSTERINSIGHTS_FORCE_ACTIVATION' ) || ! MONSTERINSIGHTS_FORCE_ACTIVATION ) ) {
558
+ deactivate_plugins( plugin_basename( __FILE__ ) );
559
+ wp_die( sprintf( esc_html__( 'Sorry, but your version of WordPress does not meet MonsterInsight\'s required version of %1$s3.8%2$s to run properly. The plugin not been activated. %3$sClick here to return to the Dashboard%4$s.', 'google-analytics-by-wordpress' ), '<strong>', '</strong>', '<a href="' . $url . '">', '</a>' ) );
560
+ }
561
+
562
+ if ( class_exists( 'MonsterInsights' ) ) {
563
+ deactivate_plugins( plugin_basename( __FILE__ ) );
564
+ wp_die( sprintf( esc_html__( 'Please uninstall and remove MonsterInsights Pro before activating Google Analytics for WordPress by MonsterInsights. The Lite version has not been activated. %1$sClick here to return to the Dashboard%2$s.', 'google-analytics-by-wordpress' ), '<a href="' . $url . '">', '</a>' ) );
565
+ }
566
+
567
+ // Add transient to trigger redirect.
568
+ set_transient( '_monsterinsights_activation_redirect', 1, 30 );
569
+ }
570
+ register_activation_hook( __FILE__, 'monsterinsights_lite_activation_hook' );
571
+
572
+ /**
573
+ * Fired when the plugin is uninstalled.
574
+ *
575
+ * @access public
576
+ * @since 6.0.0
577
+ *
578
+ * @return void
579
+ */
580
+ function monsterinsights_lite_uninstall_hook() {
581
+ wp_cache_flush();
582
+
583
+ // Note, if both MI Pro and Lite are active, this is an MI Pro instance
584
+ // Therefore MI Lite can only use functions of the instance common to
585
+ // both plugins. If it needs to be pro specific, then include a file that
586
+ // has that method.
587
+ $instance = MonsterInsights();
588
+
589
+ // If uninstalling via wp-cli load admin-specific files only here.
590
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
591
+ define( 'WP_ADMIN', true );
592
+ $instance->require_files();
593
+ $instance->load_auth();
594
+ $instance->notices = new MonsterInsights_Notice_Admin();
595
+ $instance->reporting = new MonsterInsights_Reporting();
596
+ $instance->api_auth = new MonsterInsights_API_Auth();
597
+ }
598
+
599
+ // Don't delete any data if the PRO version is already active.
600
+ if ( monsterinsights_is_pro_version() ) {
601
+ return;
602
+ }
603
+
604
+ if ( is_multisite() ) {
605
+ $site_list = get_sites();
606
+ foreach ( (array) $site_list as $site ) {
607
+ switch_to_blog( $site->blog_id );
608
+
609
+ // Delete auth
610
+ $instance->api_auth->delete_auth();
611
+
612
+ // Delete data
613
+ $instance->reporting->delete_aggregate_data('site');
614
+
615
+ restore_current_blog();
616
+ }
617
+ // Delete network auth using a custom function as some variables are not initiated.
618
+ $instance->api_auth->uninstall_network_auth();
619
+
620
+ // Delete network data
621
+ $instance->reporting->delete_aggregate_data('network');
622
+ } else {
623
+ // Delete auth
624
+ $instance->api_auth->delete_auth();
625
+
626
+ // Delete data
627
+ $instance->reporting->delete_aggregate_data('site');
628
+ }
629
+
630
+ }
631
+ register_uninstall_hook( __FILE__, 'monsterinsights_lite_uninstall_hook' );
632
+
633
+ /**
634
+ * The main function responsible for returning the one true MonsterInsights_Lite
635
+ * Instance to functions everywhere.
636
+ *
637
+ * Use this function like you would a global variable, except without needing
638
+ * to declare the global.
639
+ *
640
+ * Example: <?php $monsterinsights = MonsterInsights_Lite(); ?>
641
+ *
642
+ * @since 6.0.0
643
+ *
644
+ * @uses MonsterInsights_Lite::get_instance() Retrieve MonsterInsights_Lite instance.
645
+ *
646
+ * @return MonsterInsights_Lite The singleton MonsterInsights_Lite instance.
647
+ */
648
+ function MonsterInsights_Lite() {
649
+ return MonsterInsights_Lite::get_instance();
650
+ }
651
+
652
+ /**
653
+ * MonsterInsights Install and Updates.
654
+ *
655
+ * This function is used install and upgrade MonsterInsights. This is used for upgrade routines
656
+ * that can be done automatically, behind the scenes without the need for user interaction
657
+ * (for example pagination or user input required), as well as the initial install.
658
+ *
659
+ * @since 6.0.0
660
+ * @access public
661
+ *
662
+ * @global string $wp_version WordPress version (provided by WordPress core).
663
+ * @uses MonsterInsights_Lite::load_settings() Loads MonsterInsights settings
664
+ * @uses MonsterInsights_Install::init() Runs upgrade process
665
+ *
666
+ * @return void
667
+ */
668
+ function monsterinsights_lite_install_and_upgrade() {
669
+ global $wp_version;
670
+
671
+ // If the WordPress site doesn't meet the correct WP version requirements, don't activate MonsterInsights
672
+ if ( version_compare( $wp_version, '3.8', '<' ) ) {
673
+ if ( is_plugin_active( plugin_basename( __FILE__ ) ) ) {
674
+ return;
675
+ }
676
+ }
677
+
678
+ // Don't run if MI Pro is installed
679
+ if ( class_exists( 'MonsterInsights' ) ) {
680
+ if ( is_plugin_active( plugin_basename( __FILE__ ) ) ) {
681
+ return;
682
+ }
683
+ }
684
+
685
+
686
+ // Load settings and globals (so we can use/set them during the upgrade process)
687
+ MonsterInsights_Lite()->define_globals();
688
+ MonsterInsights_Lite()->load_settings();
689
+
690
+ // Load in Auth
691
+ MonsterInsights()->load_auth();
692
+
693
+ // Load upgrade file
694
+ require_once MONSTERINSIGHTS_PLUGIN_DIR . 'includes/install.php';
695
+
696
+ // Run the MonsterInsights upgrade routines
697
+ $updates = new MonsterInsights_Install();
698
+ $updates->init();
699
+ }
700
+
701
+ /**
702
+ * MonsterInsights check for install and update processes.
703
+ *
704
+ * This function is used to call the MonsterInsights automatic upgrade class, which in turn
705
+ * checks to see if there are any update procedures to be run, and if
706
+ * so runs them. Also installs MonsterInsights for the first time.
707
+ *
708
+ * @since 6.0.0
709
+ * @access public
710
+ *
711
+ * @uses MonsterInsights_Install() Runs install and upgrade process.
712
+ *
713
+ * @return void
714
+ */
715
+ function monsterinsights_lite_call_install_and_upgrade(){
716
+ add_action( 'wp_loaded', 'monsterinsights_lite_install_and_upgrade' );
717
+ }
718
+
719
+ /**
720
+ * Returns the MonsterInsights combined object that you can use for both
721
+ * MonsterInsights Lite and Pro Users. When both plugins active, defers to the
722
+ * more complete Pro object.
723
+ *
724
+ * Warning: Do not use this in Lite or Pro specific code (use the individual objects instead).
725
+ * Also do not use in the MonsterInsights Lite/Pro upgrade and install routines.
726
+ *
727
+ * Use this function like you would a global variable, except without needing
728
+ * to declare the global.
729
+ *
730
+ * Prevents the need to do conditional global object logic when you have code that you want to work with
731
+ * both Pro and Lite.
732
+ *
733
+ * Example: <?php $monsterinsights = MonsterInsights(); ?>
734
+ *
735
+ * @since 6.0.0
736
+ *
737
+ * @uses MonsterInsights::get_instance() Retrieve MonsterInsights Pro instance.
738
+ * @uses MonsterInsights_Lite::get_instance() Retrieve MonsterInsights Lite instance.
739
+ *
740
+ * @return MonsterInsights The singleton MonsterInsights instance.
741
+ */
742
+ if ( ! function_exists( 'MonsterInsights' ) ) {
743
+ function MonsterInsights() {
744
+ return ( class_exists( 'MonsterInsights' ) ? MonsterInsights_Pro() : MonsterInsights_Lite() );
745
+ }
746
+ add_action( 'plugins_loaded', 'MonsterInsights' );
747
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/admin.php CHANGED
@@ -1,485 +1,483 @@
1
- <?php
2
- /**
3
- * Admin class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Admin
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- /**
18
- * Register menu items for MonsterInsights.
19
- *
20
- * @since 6.0.0
21
- * @access public
22
- *
23
- * @return void
24
- */
25
- function monsterinsights_admin_menu() {
26
-
27
- // Get the base class object.
28
- $base = MonsterInsights();
29
-
30
- $dashboards_disabled = monsterinsights_get_option( 'dashboards_disabled', false );
31
- $is_authed = ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() );
32
-
33
- $hook = 'monsterinsights_settings';
34
- $menu_icon_inline = monsterinsights_get_inline_menu_icon();
35
-
36
- if ( $dashboards_disabled || ! $is_authed || ( current_user_can( 'monsterinsights_save_settings' ) && ! current_user_can( 'monsterinsights_view_dashboard' ) ) ) {
37
- // If dashboards disabled, first settings page
38
- add_menu_page( __( 'MonsterInsights', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_settings', 'monsterinsights_settings_page', $menu_icon_inline, '100.00013467543' );
39
- $hook = 'monsterinsights_settings';
40
-
41
- add_submenu_page( $hook, __( 'MonsterInsights', 'google-analytics-for-wordpress' ), __( 'Settings', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_settings' );
42
- } else {
43
- // if dashboards enabled, first dashboard
44
- add_menu_page( __( 'General:', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'monsterinsights_reports', 'monsterinsights_reports_page', $menu_icon_inline, '100.00013467543' );
45
-
46
- $hook = 'monsterinsights_reports';
47
-
48
- add_submenu_page( $hook, __( 'General Reports:', 'google-analytics-for-wordpress' ), __( 'Reports', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'monsterinsights_reports', 'monsterinsights_reports_page' );
49
-
50
- // then settings page
51
- add_submenu_page( $hook, __( 'MonsterInsights', 'google-analytics-for-wordpress' ), __( 'Settings', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_settings', 'monsterinsights_settings_page' );
52
-
53
- // Add dashboard submenu.
54
- add_submenu_page( 'index.php', __( 'General Reports:', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'admin.php?page=monsterinsights_reports' );
55
- }
56
-
57
- $submenu_base = add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) );
58
-
59
- // then tools
60
- add_submenu_page( $hook, __( 'Tools:', 'google-analytics-for-wordpress' ), __( 'Tools', 'google-analytics-for-wordpress' ), 'manage_options', $submenu_base . '#/tools' );
61
-
62
- // then addons
63
- $network_key = MonsterInsights()->license->get_network_license_key();
64
- if ( ! monsterinsights_is_network_active() || ( monsterinsights_is_network_active() && empty( $network_key ) ) ) {
65
- add_submenu_page( $hook, __( 'Addons:', 'google-analytics-for-wordpress' ), '<span style="color:#7cc048"> ' . __( 'Addons', 'google-analytics-for-wordpress' ) . '</span>', 'monsterinsights_save_settings', $submenu_base . '#/addons' );
66
- }
67
-
68
- // Add About us page.
69
- add_submenu_page( $hook, __( 'About Us:', 'google-analytics-for-wordpress' ), __( 'About Us', 'google-analytics-for-wordpress' ), 'manage_options', $submenu_base . '#/about' );
70
- }
71
- add_action( 'admin_menu', 'monsterinsights_admin_menu' );
72
-
73
-
74
-
75
- function monsterinsights_network_admin_menu() {
76
- // Get the base class object.
77
- $base = MonsterInsights();
78
-
79
- // First, let's see if this is an MS network enabled plugin. If it is, we should load the license
80
- // menu page and the updater on the network panel
81
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
82
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
83
- }
84
-
85
- $plugin = plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE );
86
- if ( ! is_plugin_active_for_network( $plugin ) ) {
87
- return;
88
- }
89
-
90
- $menu_icon_inline = monsterinsights_get_inline_menu_icon();
91
- $hook = 'monsterinsights_network';
92
- $submenu_base = add_query_arg( 'page', 'monsterinsights_network', network_admin_url( 'admin.php' ) );
93
- add_menu_page( __( 'Network Settings:', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_network', 'monsterinsights_network_page', $menu_icon_inline, '100.00013467543' );
94
-
95
- add_submenu_page( $hook, __( 'Network Settings:', 'google-analytics-for-wordpress' ), __( 'Network Settings', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_network', 'monsterinsights_network_page' );
96
-
97
- add_submenu_page( $hook, __( 'General Reports:', 'google-analytics-for-wordpress' ), __( 'Reports', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'monsterinsights_reports', 'monsterinsights_reports_page' );
98
-
99
- // then addons
100
- add_submenu_page( $hook, __( 'Addons:', 'google-analytics-for-wordpress' ), '<span style="color:#7cc048"> ' . __( 'Addons', 'google-analytics-for-wordpress' ) . '</span>', 'monsterinsights_save_settings', $submenu_base . '#/addons' );
101
- }
102
- add_action( 'network_admin_menu', 'monsterinsights_network_admin_menu', 5 );
103
-
104
- /**
105
- * Adds one or more classes to the body tag in the dashboard.
106
- *
107
- * @param String $classes Current body classes.
108
- * @return String Altered body classes.
109
- */
110
- function monsterinsights_add_admin_body_class( $classes ) {
111
- $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
112
- if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
113
- return $classes;
114
- }
115
-
116
- return "$classes monsterinsights_page ";
117
- }
118
- add_filter( 'admin_body_class', 'monsterinsights_add_admin_body_class', 10, 1 );
119
-
120
- /**
121
- * Adds one or more classes to the body tag in the dashboard.
122
- *
123
- * @param String $classes Current body classes.
124
- * @return String Altered body classes.
125
- */
126
- function monsterinsights_add_admin_body_class_tools_page( $classes ) {
127
- $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
128
-
129
- if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights_tools' ) === false || 'insights_page_monsterinsights_tools' === $screen->id ) {
130
- return $classes;
131
- }
132
-
133
- return "$classes insights_page_monsterinsights_tools ";
134
- }
135
- add_filter( 'admin_body_class', 'monsterinsights_add_admin_body_class_tools_page', 10, 1 );
136
-
137
- /**
138
- * Adds one or more classes to the body tag in the dashboard.
139
- *
140
- * @param String $classes Current body classes.
141
- * @return String Altered body classes.
142
- */
143
- function monsterinsights_add_admin_body_class_addons_page( $classes ) {
144
- $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
145
- if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights_addons' ) === false || 'insights_page_monsterinsights_addons' === $screen->id ) {
146
- return $classes;
147
- }
148
-
149
- return "$classes insights_page_monsterinsights_addons ";
150
- }
151
- add_filter( 'admin_body_class', 'monsterinsights_add_admin_body_class_addons_page', 10, 1 );
152
-
153
- /**
154
- * Add a link to the settings page to the plugins list
155
- *
156
- * @param array $links array of links for the plugins, adapted when the current plugin is found.
157
- *
158
- * @return array $links
159
- */
160
- function monsterinsights_add_action_links( $links ) {
161
- $docs = '<a title="' . esc_html__( 'MonsterInsights Knowledge Base', 'google-analytics-for-wordpress' ) . '" href="'. monsterinsights_get_url( 'all-plugins', 'kb-link', "https://www.monsterinsights.com/docs/" ) .'"">' . esc_html__( 'Documentation', 'google-analytics-for-wordpress' ) . '</a>';
162
- array_unshift( $links, $docs );
163
-
164
- // If lite, show a link where they can get pro from
165
- if ( ! monsterinsights_is_pro_version() ) {
166
- $get_pro = '<a title="' . esc_html__( 'Get MonsterInsights Pro', 'google-analytics-for-wordpress' ) .'" href="'. monsterinsights_get_upgrade_link( 'all-plugins', 'upgrade-link', "https://www.monsterinsights.com/docs/" ) .'">' . esc_html__( 'Get MonsterInsights Pro', 'google-analytics-for-wordpress' ) . '</a>';
167
- array_unshift( $links, $get_pro );
168
- }
169
-
170
- // If Lite, support goes to forum. If pro, it goes to our website
171
- if ( monsterinsights_is_pro_version() ) {
172
- $support = '<a title="MonsterInsights Pro Support" href="'. monsterinsights_get_url( 'all-plugins', 'pro-support-link', "https://www.monsterinsights.com/my-account/support/" ) .'">' . esc_html__( 'Support', 'google-analytics-for-wordpress' ) . '</a>';
173
- array_unshift( $links, $support );
174
- } else {
175
- $support = '<a title="MonsterInsights Lite Support" href="'. monsterinsights_get_url( 'all-plugins', 'lite-support-link', "https://www.monsterinsights.com/lite-support/" ) .'">' . esc_html__( 'Support', 'google-analytics-for-wordpress' ) . '</a>';
176
- array_unshift( $links, $support );
177
- }
178
-
179
- $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=monsterinsights_settings' ) ) . '">' . esc_html__( 'Settings', 'google-analytics-for-wordpress' ) . '</a>';
180
- array_unshift( $links, $settings_link );
181
-
182
- return $links;
183
- }
184
- add_filter( 'plugin_action_links_' . plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ), 'monsterinsights_add_action_links' );
185
-
186
-
187
-
188
- /**
189
- * Loads a partial view for the Administration screen
190
- *
191
- * @access public
192
- * @since 6.0.0
193
- *
194
- * @param string $template PHP file at includes/admin/partials, excluding file extension
195
- * @param array $data Any data to pass to the view
196
- * @return void
197
- */
198
- function monsterinsights_load_admin_partial( $template, $data = array() ) {
199
-
200
- if ( monsterinsights_is_pro_version() ) {
201
- $dir = trailingslashit( plugin_dir_path( MonsterInsights()->file ) . 'pro/includes/admin/partials' );
202
-
203
- if ( file_exists( $dir . $template . '.php' ) ) {
204
- require_once( $dir . $template . '.php' );
205
- return true;
206
- }
207
- } else {
208
- $dir = trailingslashit( plugin_dir_path( MonsterInsights()->file ) . 'lite/includes/admin/partials' );
209
-
210
- if ( file_exists( $dir . $template . '.php' ) ) {
211
- require_once( $dir . $template . '.php' );
212
- return true;
213
- }
214
- }
215
-
216
- $dir = trailingslashit( plugin_dir_path( MonsterInsights()->file ) . 'includes/admin/partials' );
217
-
218
- if ( file_exists( $dir . $template . '.php' ) ) {
219
- require_once( $dir . $template . '.php' );
220
- return true;
221
- }
222
-
223
- return false;
224
- }
225
-
226
- /**
227
- * When user is on a MonsterInsights related admin page, display footer text
228
- * that graciously asks them to rate us.
229
- *
230
- * @since 6.0.0
231
- * @param string $text
232
- * @return string
233
- */
234
- function monsterinsights_admin_footer( $text ) {
235
- global $current_screen;
236
- if ( ! empty( $current_screen->id ) && strpos( $current_screen->id, 'monsterinsights' ) !== false ) {
237
- $url = 'https://wordpress.org/support/view/plugin-reviews/google-analytics-for-wordpress?filter=5';
238
- $text = sprintf( esc_html__( 'Please rate %sMonsterInsights%s %s on %sWordPress.org%s to help us spread the word. Thank you from the MonsterInsights team!', 'google-analytics-for-wordpress' ), '<strong>', '</strong>', '<a class="monsterinsights-no-text-decoration" href="' . $url . '" target="_blank" rel="noopener noreferrer"><i class="monstericon-star"></i><i class="monstericon-star"></i><i class="monstericon-star"></i><i class="monstericon-star"></i><i class="monstericon-star"></i></a>', '<a href="' . $url . '" target="_blank" rel="noopener noreferrer">', '</a>' );
239
- }
240
- return $text;
241
- }
242
- add_filter( 'admin_footer_text', 'monsterinsights_admin_footer', 1, 2 );
243
-
244
- function monsterinsights_admin_setup_notices() {
245
-
246
- // Don't show on MonsterInsights pages
247
- $screen = get_current_screen();
248
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) !== false ) {
249
- return;
250
- }
251
-
252
- // Make sure they have the permissions to do something
253
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
254
- return;
255
- }
256
-
257
- // Priority:
258
- // 1. Google Analytics not authenticated
259
- // 2. License key not entered for pro
260
- // 3. License key not valid/okay for pro
261
- // 4. WordPress + PHP min versions
262
- // 5. (old) Optin setting not configured
263
- // 6. Manual UA code
264
- // 7. Automatic updates not configured
265
- // 8. Woo upsell
266
- // 9. EDD upsell
267
-
268
-
269
- // 1. Google Analytics not authenticated
270
- if ( ! is_network_admin() && ! monsterinsights_get_ua() ) {
271
- $page = admin_url( 'admin.php?page=monsterinsights_settings' );
272
- $message = sprintf( esc_html__( 'Please configure your %1$sGoogle Analytics settings%2$s!', 'google-analytics-for-wordpress' ),'<a href="' . $page . '">', '</a>' );
273
- echo '<div class="error"><p>'. $message.'</p></div>';
274
- return;
275
- }
276
-
277
- // 2. License key not entered for pro
278
- $key = monsterinsights_is_pro_version() ? MonsterInsights()->license->get_license_key() : '';
279
- if ( monsterinsights_is_pro_version() && empty( $key ) ) {
280
- $page = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
281
- $message = sprintf( esc_html__( 'Warning: No valid license key has been entered for MonsterInsights. You are currently not getting updates, and are not able to view reports. %1$sPlease click here to enter your license key and begin receiving updates and reports.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. esc_url( $page ) . '">', '</a>' );
282
- echo '<div class="error"><p>'. $message.'</p></div>';
283
- return;
284
- }
285
-
286
- // 3. License key not valid/okay for pro
287
- if ( monsterinsights_is_pro_version() ) {
288
- $message = '';
289
- if ( MonsterInsights()->license->get_site_license_key() ){
290
- if ( MonsterInsights()->license->site_license_expired() ) {
291
- $message = sprintf( esc_html__( 'Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. monsterinsights_get_url( 'admin-notices', 'expired-license', "https://www.monsterinsights.com/login/" ) .'" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
292
- } else if ( MonsterInsights()->license->site_license_disabled() ) {
293
- $message = esc_html__( 'Your license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
294
- } else if ( MonsterInsights()->license->site_license_invalid() ) {
295
- $message = esc_html__( 'Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
296
- }
297
- } else if ( MonsterInsights()->license->get_network_license_key() ) {
298
- if ( MonsterInsights()->license->network_license_expired() ) {
299
- $message = sprintf( esc_html__( 'Your network license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. monsterinsights_get_url( 'admin-notices', 'expired-license', "https://www.monsterinsights.com/login/" ) .'" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
300
- } else if ( MonsterInsights()->license->network_license_disabled() ) {
301
- $message = esc_html__( 'Your network license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
302
- } else if ( MonsterInsights()->license->network_license_invalid() ) {
303
- $message = esc_html__( 'Your network license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
304
- }
305
- }
306
- if ( ! empty( $message ) ) {
307
- echo '<div class="error"><p>'. $message.'</p></div>';
308
- return;
309
- }
310
- }
311
-
312
- // 4. Notices for PHP/WP version deprecations
313
- if ( current_user_can( 'update_core' ) ) {
314
- global $wp_version;
315
-
316
- // PHP 5.2/5.3
317
- if ( version_compare( phpversion(), '5.4', '<' ) ) {
318
- $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' );
319
- $message = sprintf( esc_html__( 'Your site is running an outdated, insecure version of PHP (%1$s), which could be putting your site at risk for being hacked.%4$sWordPress will stop supporting your PHP version in April, 2019.%4$sUpdating PHP only takes a few minutes and will make your website significantly faster and more secure.%4$s%2$sLearn more about updating PHP%3$s', 'google-analytics-for-wordpress' ), phpversion(), '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
320
- echo '<div class="error"><p>'. $message.'</p></div>';
321
- return;
322
- }
323
- // WordPress 3.0 - 4.5
324
- else if ( version_compare( $wp_version, '4.6', '<' ) ) {
325
- $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' );
326
- $message = sprintf( esc_html__( 'Your site is running an outdated version of WordPress (%1$s).%4$sMonsterInsights will stop supporting WordPress versions lower than 4.6 in April, 2019.%4$sUpdating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install.%4$s%2$sLearn more about updating WordPress%3$s', 'google-analytics-for-wordpress' ), $wp_version, '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
327
- echo '<div class="error"><p>'. $message.'</p></div>';
328
- return;
329
- }
330
- // PHP 5.4/5.5
331
- // else if ( version_compare( phpversion(), '5.6', '<' ) ) {
332
- // $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' );
333
- // $message = sprintf( esc_html__( 'Your site is running an outdated, insecure version of PHP (%1$s), which could be putting your site at risk for being hacked.%4$sWordPress will stop supporting your PHP version in April, 2019.%4$sUpdating PHP only takes a few minutes and will make your website significantly faster and more secure.%4$s%2$sLearn more about updating PHP%3$s', 'google-analytics-for-wordpress' ), phpversion(), '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
334
- // echo '<div class="error"><p>'. $message.'</p></div>';
335
- // return;
336
- // }
337
- // // WordPress 4.6 - 4.8
338
- // else if ( version_compare( $wp_version, '4.9', '<' ) ) {
339
- // $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' );
340
- // $message = sprintf( esc_html__( 'Your site is running an outdated version of WordPress (%1$s).%4$sMonsterInsights will stop supporting WordPress versions lower than 4.9 in October, 2019.%4$sUpdating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install.%4$s%2$sLearn more about updating WordPress%3$s', 'google-analytics-for-wordpress' ), $wp_version, '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
341
- // echo '<div class="error"><p>'. $message.'</p></div>';
342
- // return;
343
- // }
344
- }
345
-
346
- // 5. Optin setting not configured
347
- // if ( ! is_network_admin() ) {
348
- // if ( ! get_option( 'monsterinsights_tracking_notice' ) ) {
349
- // if ( ! monsterinsights_get_option( 'anonymous_data', false ) ) {
350
- // if ( ! monsterinsights_is_dev_url( network_site_url( '/' ) ) ) {
351
- // if ( monsterinsights_is_pro_version() ) {
352
- // monsterinsights_update_option( 'anonymous_data', 1 );
353
- // return;
354
- // }
355
- // $optin_url = add_query_arg( 'mi_action', 'opt_into_tracking' );
356
- // $optout_url = add_query_arg( 'mi_action', 'opt_out_of_tracking' );
357
- // echo '<div class="updated"><p>';
358
- // echo esc_html__( 'Allow MonsterInsights to track plugin usage? Opt-in to tracking and our newsletter to stay informed of the latest changes to MonsterInsights and help us ensure compatibility.', 'google-analytics-for-wordpress' );
359
- // echo '&nbsp;<a href="' . esc_url( $optin_url ) . '" class="button-secondary">' . __( 'Allow', 'google-analytics-for-wordpress' ) . '</a>';
360
- // echo '&nbsp;<a href="' . esc_url( $optout_url ) . '" class="button-secondary">' . __( 'Do not allow', 'google-analytics-for-wordpress' ) . '</a>';
361
- // echo '</p></div>';
362
- // return;
363
- // } else {
364
- // // is testing site
365
- // update_option( 'monsterinsights_tracking_notice', '1' );
366
- // }
367
- // }
368
- // }
369
- // }
370
-
371
- $notices = get_option( 'monsterinsights_notices' );
372
- if ( ! is_array( $notices ) ) {
373
- $notices = array();
374
- }
375
-
376
- // 6. Authenticate, not manual
377
- $authed = MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed();
378
- $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
379
-
380
- if ( empty( $authed ) && ! isset( $notices['monsterinsights_auth_not_manual' ] ) ) {
381
- echo '<div class="notice notice-info is-dismissible monsterinsights-notice" data-notice="monsterinsights_auth_not_manual">';
382
- echo '<p>';
383
- echo sprintf( esc_html__( 'Important: You are currently using manual UA code output. We highly recommend %1$sauthenticating with MonsterInsights%2$s so that you can access our new reporting area and take advantage of new MonsterInsights features.', 'google-analytics-for-wordpress' ), '<a href="' . $url .'">', '</a>' );
384
- echo '</p>';
385
- echo '</div>';
386
- return;
387
- }
388
-
389
- // 7. Automatic updates not configured
390
- // if ( ! is_network_admin() ) {
391
- // $updates = monsterinsights_get_option( 'automatic_updates', false );
392
- // $url = admin_url( 'admin.php?page=monsterinsights_settings' );
393
-
394
- // if ( empty( $updates) && ! isset( $notices['monsterinsights_automatic_updates' ] ) ) {
395
- // echo '<div class="notice notice-info is-dismissible monsterinsights-notice" data-notice="monsterinsights_automatic_updates">';
396
- // echo '<p>';
397
- // echo sprintf( esc_html__( 'Important: Please %1$sconfigure the Automatic Updates Settings%2$s in MonsterInsights.', 'google-analytics-for-wordpress' ), '<a href="' . $url .'">', '</a>' );
398
- // echo '</p>';
399
- // echo '</div>';
400
- // return;
401
- // }
402
- // }
403
-
404
- // 8. WooUpsell
405
- if ( ! monsterinsights_is_pro_version() && class_exists( 'WooCommerce' ) ) {
406
- if ( ! isset( $notices['monsterinsights_woocommerce_tracking_available' ] ) ) {
407
- echo '<div class="notice notice-success is-dismissible monsterinsights-notice monsterinsights-wooedd-upsell-row" data-notice="monsterinsights_woocommerce_tracking_available">';
408
- echo '<div class="monsterinsights-wooedd-upsell-left">';
409
- echo '<p><strong>';
410
- echo esc_html( 'Enhanced Ecommerce Analytics for Your WooCommerce Store', 'google-analytics-for-wordpress' );
411
- echo '</strong></p>';
412
- echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-small" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
413
- echo '<p>';
414
- echo esc_html( 'MonsterInsights Pro gives you detailed stats and insights about your customers.', 'google-analytics-for-wordpress' );
415
- echo '</p>';
416
- echo '<p>';
417
- echo esc_html( 'This helps you make data-driven decisions about your content, and marketing strategy so you can increase your website traffic, leads, and sales.', 'google-analytics-for-wordpress' );
418
- echo '</p>';
419
- echo '<p>';
420
- echo esc_html( 'Pro customers also get Form Tracking, Custom Dimensions Tracking, UserID Tracking and much more.', 'google-analytics-for-wordpress' );
421
- echo '</p>';
422
- echo '<p>';
423
- echo esc_html( 'Start making data-driven decisions to grow your business.', 'google-analytics-for-wordpress' );
424
- echo '</p>';
425
- echo sprintf( esc_html__( '%1$sGet MonsterInsights Pro%2$s', 'google-analytics-for-wordpress' ), '<a class="button button-primary button-hero" href="'. monsterinsights_get_upgrade_link( 'admin-notices', 'woocommerce-upgrade' ) .'">', ' &raquo;</a>' );
426
- echo '</p>';
427
- echo '</div><div class="monsterinsights-wooedd-upsell-right">';
428
- echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-large" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
429
- echo '</div>';
430
- echo '</div>';
431
- return;
432
- }
433
- }
434
-
435
- // 9. EDDUpsell
436
- if ( ! monsterinsights_is_pro_version() && class_exists( 'Easy_Digital_Downloads' ) ) {
437
- if ( ! isset( $notices['monsterinsights_edd_tracking_available' ] ) ) {
438
- echo '<div class="notice notice-success is-dismissible monsterinsights-notice monsterinsights-wooedd-upsell-row" data-notice="monsterinsights_edd_tracking_available">';
439
- echo '<div class="monsterinsights-wooedd-upsell-left">';
440
- echo '<p><strong>';
441
- echo esc_html( 'Enhanced Ecommerce Analytics for Your Easy Digital Downloads Store', 'google-analytics-for-wordpress' );
442
- echo '</strong></p>';
443
- echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-small" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
444
- echo '<p>';
445
- echo esc_html( 'MonsterInsights Pro gives you detailed stats and insights about your customers.', 'google-analytics-for-wordpress' );
446
- echo '</p>';
447
- echo '<p>';
448
- echo esc_html( 'This helps you make data-driven decisions about your content, and marketing strategy so you can increase your website traffic, leads, and sales.', 'google-analytics-for-wordpress' );
449
- echo '</p>';
450
- echo '<p>';
451
- echo esc_html( 'Pro customers also get Form Tracking, Custom Dimensions Tracking, UserID Tracking and much more.', 'google-analytics-for-wordpress' );
452
- echo '</p>';
453
- echo '<p>';
454
- echo esc_html( 'Start making data-driven decisions to grow your business.', 'google-analytics-for-wordpress' );
455
- echo '</p>';
456
- echo sprintf( esc_html__( '%1$sGet MonsterInsights Pro%2$s', 'google-analytics-for-wordpress' ), '<a class="button button-primary button-hero" href="'. monsterinsights_get_upgrade_link( 'admin-notices', 'edd-upgrade' ) .'">', ' &raquo;</a>' );
457
- echo '</p>';
458
- echo '</div><div class="monsterinsights-wooedd-upsell-right">';
459
- echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-large" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
460
- echo '</div>';
461
- echo '</div>';
462
- return;
463
- }
464
- }
465
-
466
- if ( isset( $notices['monsterinsights_cross_domains_extracted'] ) && false === $notices['monsterinsights_cross_domains_extracted'] ) {
467
- $page = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
468
- $page = $page . '#/advanced';
469
- $message = sprintf( esc_html__( 'Warning: MonsterInsights found cross-domain settings in the custom code field and converted them to the new settings structure. %1$sPlease click here to review and remove the code no longer needed.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. esc_url( $page ) . '">', '</a>' );
470
- echo '<div class="notice notice-success is-dismissible monsterinsights-notice" data-notice="monsterinsights_cross_domains_extracted"><p>'. $message.'</p></div>';
471
- return;
472
- }
473
- }
474
- add_action( 'admin_notices', 'monsterinsights_admin_setup_notices' );
475
- add_action( 'network_admin_notices', 'monsterinsights_admin_setup_notices' );
476
-
477
-
478
- // AM Notices
479
- function monsterinsights_am_notice_optout( $super_admin ) {
480
- if ( monsterinsights_get_option( 'hide_am_notices', false ) || monsterinsights_get_option( 'network_hide_am_notices', false ) ) {
481
- return false;
482
- }
483
- return $super_admin;
484
- }
485
- add_filter( "am_notifications_display", 'monsterinsights_am_notice_optout', 10, 1 );
1
+ <?php
2
+ /**
3
+ * Admin class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Admin
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ /**
18
+ * Register menu items for MonsterInsights.
19
+ *
20
+ * @since 6.0.0
21
+ * @access public
22
+ *
23
+ * @return void
24
+ */
25
+ function monsterinsights_admin_menu() {
26
+
27
+ // Get the base class object.
28
+ $base = MonsterInsights();
29
+
30
+ $dashboards_disabled = monsterinsights_get_option( 'dashboards_disabled', false );
31
+ $is_authed = ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() );
32
+
33
+ $hook = 'monsterinsights_settings';
34
+ $menu_icon_inline = monsterinsights_get_inline_menu_icon();
35
+
36
+ if ( $dashboards_disabled || ( current_user_can( 'monsterinsights_save_settings' ) && ! current_user_can( 'monsterinsights_view_dashboard' ) ) ) {
37
+ // If dashboards disabled, first settings page
38
+ add_menu_page( __( 'MonsterInsights', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_settings', 'monsterinsights_settings_page', $menu_icon_inline, '100.00013467543' );
39
+ $hook = 'monsterinsights_settings';
40
+
41
+ add_submenu_page( $hook, __( 'MonsterInsights', 'google-analytics-for-wordpress' ), __( 'Settings', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_settings' );
42
+ } else {
43
+ // if dashboards enabled, first dashboard
44
+ add_menu_page( __( 'General:', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'monsterinsights_reports', 'monsterinsights_reports_page', $menu_icon_inline, '100.00013467543' );
45
+
46
+ $hook = 'monsterinsights_reports';
47
+
48
+ add_submenu_page( $hook, __( 'General Reports:', 'google-analytics-for-wordpress' ), __( 'Reports', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'monsterinsights_reports', 'monsterinsights_reports_page' );
49
+
50
+ // then settings page
51
+ add_submenu_page( $hook, __( 'MonsterInsights', 'google-analytics-for-wordpress' ), __( 'Settings', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_settings', 'monsterinsights_settings_page' );
52
+
53
+ // Add dashboard submenu.
54
+ add_submenu_page( 'index.php', __( 'General Reports:', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'admin.php?page=monsterinsights_reports' );
55
+ }
56
+
57
+ $submenu_base = add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) );
58
+
59
+ // then tools
60
+ add_submenu_page( $hook, __( 'Tools:', 'google-analytics-for-wordpress' ), __( 'Tools', 'google-analytics-for-wordpress' ), 'manage_options', $submenu_base . '#/tools' );
61
+
62
+ // then addons
63
+ $network_key = monsterinsights_is_pro_version() ? MonsterInsights()->license->get_network_license_key() : '';
64
+ if ( ! monsterinsights_is_network_active() || ( monsterinsights_is_network_active() && empty( $network_key ) ) ) {
65
+ add_submenu_page( $hook, __( 'Addons:', 'google-analytics-for-wordpress' ), '<span style="color:' . monsterinsights_menu_highlight_color() . '"> ' . __( 'Addons', 'google-analytics-for-wordpress' ) . '</span>', 'monsterinsights_save_settings', $submenu_base . '#/addons' );
66
+ }
67
+
68
+ // Add About us page.
69
+ add_submenu_page( $hook, __( 'About Us:', 'google-analytics-for-wordpress' ), __( 'About Us', 'google-analytics-for-wordpress' ), 'manage_options', $submenu_base . '#/about' );
70
+ }
71
+ add_action( 'admin_menu', 'monsterinsights_admin_menu' );
72
+
73
+ function monsterinsights_network_admin_menu() {
74
+ // Get the base class object.
75
+ $base = MonsterInsights();
76
+
77
+ // First, let's see if this is an MS network enabled plugin. If it is, we should load the license
78
+ // menu page and the updater on the network panel
79
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
80
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
81
+ }
82
+
83
+ $plugin = plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE );
84
+ if ( ! is_plugin_active_for_network( $plugin ) ) {
85
+ return;
86
+ }
87
+
88
+ $menu_icon_inline = monsterinsights_get_inline_menu_icon();
89
+ $hook = 'monsterinsights_network';
90
+ $submenu_base = add_query_arg( 'page', 'monsterinsights_network', network_admin_url( 'admin.php' ) );
91
+ add_menu_page( __( 'Network Settings:', 'google-analytics-for-wordpress' ), __( 'Insights', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_network', 'monsterinsights_network_page', $menu_icon_inline, '100.00013467543' );
92
+
93
+ add_submenu_page( $hook, __( 'Network Settings:', 'google-analytics-for-wordpress' ), __( 'Network Settings', 'google-analytics-for-wordpress' ), 'monsterinsights_save_settings', 'monsterinsights_network', 'monsterinsights_network_page' );
94
+
95
+ add_submenu_page( $hook, __( 'General Reports:', 'google-analytics-for-wordpress' ), __( 'Reports', 'google-analytics-for-wordpress' ), 'monsterinsights_view_dashboard', 'monsterinsights_reports', 'monsterinsights_reports_page' );
96
+
97
+ // then addons
98
+ add_submenu_page( $hook, __( 'Addons:', 'google-analytics-for-wordpress' ), '<span style="color:' . monsterinsights_menu_highlight_color() . '"> ' . __( 'Addons', 'google-analytics-for-wordpress' ) . '</span>', 'monsterinsights_save_settings', $submenu_base . '#/addons' );
99
+ }
100
+ add_action( 'network_admin_menu', 'monsterinsights_network_admin_menu', 5 );
101
+
102
+ /**
103
+ * Adds one or more classes to the body tag in the dashboard.
104
+ *
105
+ * @param String $classes Current body classes.
106
+ * @return String Altered body classes.
107
+ */
108
+ function monsterinsights_add_admin_body_class( $classes ) {
109
+ $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
110
+ if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
111
+ return $classes;
112
+ }
113
+
114
+ return "$classes monsterinsights_page ";
115
+ }
116
+ add_filter( 'admin_body_class', 'monsterinsights_add_admin_body_class', 10, 1 );
117
+
118
+ /**
119
+ * Adds one or more classes to the body tag in the dashboard.
120
+ *
121
+ * @param String $classes Current body classes.
122
+ * @return String Altered body classes.
123
+ */
124
+ function monsterinsights_add_admin_body_class_tools_page( $classes ) {
125
+ $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
126
+
127
+ if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights_tools' ) === false || 'insights_page_monsterinsights_tools' === $screen->id ) {
128
+ return $classes;
129
+ }
130
+
131
+ return "$classes insights_page_monsterinsights_tools ";
132
+ }
133
+ add_filter( 'admin_body_class', 'monsterinsights_add_admin_body_class_tools_page', 10, 1 );
134
+
135
+ /**
136
+ * Adds one or more classes to the body tag in the dashboard.
137
+ *
138
+ * @param String $classes Current body classes.
139
+ * @return String Altered body classes.
140
+ */
141
+ function monsterinsights_add_admin_body_class_addons_page( $classes ) {
142
+ $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
143
+ if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights_addons' ) === false || 'insights_page_monsterinsights_addons' === $screen->id ) {
144
+ return $classes;
145
+ }
146
+
147
+ return "$classes insights_page_monsterinsights_addons ";
148
+ }
149
+ add_filter( 'admin_body_class', 'monsterinsights_add_admin_body_class_addons_page', 10, 1 );
150
+
151
+ /**
152
+ * Add a link to the settings page to the plugins list
153
+ *
154
+ * @param array $links array of links for the plugins, adapted when the current plugin is found.
155
+ *
156
+ * @return array $links
157
+ */
158
+ function monsterinsights_add_action_links( $links ) {
159
+ $docs = '<a title="' . esc_html__( 'MonsterInsights Knowledge Base', 'google-analytics-for-wordpress' ) . '" href="'. monsterinsights_get_url( 'all-plugins', 'kb-link', "https://www.monsterinsights.com/docs/" ) .'"">' . esc_html__( 'Documentation', 'google-analytics-for-wordpress' ) . '</a>';
160
+ array_unshift( $links, $docs );
161
+
162
+ // If lite, show a link where they can get pro from
163
+ if ( ! monsterinsights_is_pro_version() ) {
164
+ $get_pro = '<a title="' . esc_html__( 'Get MonsterInsights Pro', 'google-analytics-for-wordpress' ) .'" href="'. monsterinsights_get_upgrade_link( 'all-plugins', 'upgrade-link', "https://www.monsterinsights.com/docs/" ) .'">' . esc_html__( 'Get MonsterInsights Pro', 'google-analytics-for-wordpress' ) . '</a>';
165
+ array_unshift( $links, $get_pro );
166
+ }
167
+
168
+ // If Lite, support goes to forum. If pro, it goes to our website
169
+ if ( monsterinsights_is_pro_version() ) {
170
+ $support = '<a title="MonsterInsights Pro Support" href="'. monsterinsights_get_url( 'all-plugins', 'pro-support-link', "https://www.monsterinsights.com/my-account/support/" ) .'">' . esc_html__( 'Support', 'google-analytics-for-wordpress' ) . '</a>';
171
+ array_unshift( $links, $support );
172
+ } else {
173
+ $support = '<a title="MonsterInsights Lite Support" href="'. monsterinsights_get_url( 'all-plugins', 'lite-support-link', "https://www.monsterinsights.com/lite-support/" ) .'">' . esc_html__( 'Support', 'google-analytics-for-wordpress' ) . '</a>';
174
+ array_unshift( $links, $support );
175
+ }
176
+
177
+ $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=monsterinsights_settings' ) ) . '">' . esc_html__( 'Settings', 'google-analytics-for-wordpress' ) . '</a>';
178
+ array_unshift( $links, $settings_link );
179
+
180
+ return $links;
181
+ }
182
+ add_filter( 'plugin_action_links_' . plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ), 'monsterinsights_add_action_links' );
183
+
184
+
185
+
186
+ /**
187
+ * Loads a partial view for the Administration screen
188
+ *
189
+ * @access public
190
+ * @since 6.0.0
191
+ *
192
+ * @param string $template PHP file at includes/admin/partials, excluding file extension
193
+ * @param array $data Any data to pass to the view
194
+ * @return void
195
+ */
196
+ function monsterinsights_load_admin_partial( $template, $data = array() ) {
197
+
198
+ if ( monsterinsights_is_pro_version() ) {
199
+ $dir = trailingslashit( plugin_dir_path( MonsterInsights()->file ) . 'pro/includes/admin/partials' );
200
+
201
+ if ( file_exists( $dir . $template . '.php' ) ) {
202
+ require_once( $dir . $template . '.php' );
203
+ return true;
204
+ }
205
+ } else {
206
+ $dir = trailingslashit( plugin_dir_path( MonsterInsights()->file ) . 'lite/includes/admin/partials' );
207
+
208
+ if ( file_exists( $dir . $template . '.php' ) ) {
209
+ require_once( $dir . $template . '.php' );
210
+ return true;
211
+ }
212
+ }
213
+
214
+ $dir = trailingslashit( plugin_dir_path( MonsterInsights()->file ) . 'includes/admin/partials' );
215
+
216
+ if ( file_exists( $dir . $template . '.php' ) ) {
217
+ require_once( $dir . $template . '.php' );
218
+ return true;
219
+ }
220
+
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * When user is on a MonsterInsights related admin page, display footer text
226
+ * that graciously asks them to rate us.
227
+ *
228
+ * @since 6.0.0
229
+ * @param string $text
230
+ * @return string
231
+ */
232
+ function monsterinsights_admin_footer( $text ) {
233
+ global $current_screen;
234
+ if ( ! empty( $current_screen->id ) && strpos( $current_screen->id, 'monsterinsights' ) !== false ) {
235
+ $url = 'https://wordpress.org/support/view/plugin-reviews/google-analytics-for-wordpress?filter=5';
236
+ $text = sprintf( esc_html__( 'Please rate %sMonsterInsights%s %s on %sWordPress.org%s to help us spread the word. Thank you from the MonsterInsights team!', 'google-analytics-for-wordpress' ), '<strong>', '</strong>', '<a class="monsterinsights-no-text-decoration" href="' . $url . '" target="_blank" rel="noopener noreferrer"><i class="monstericon-star"></i><i class="monstericon-star"></i><i class="monstericon-star"></i><i class="monstericon-star"></i><i class="monstericon-star"></i></a>', '<a href="' . $url . '" target="_blank" rel="noopener noreferrer">', '</a>' );
237
+ }
238
+ return $text;
239
+ }
240
+ add_filter( 'admin_footer_text', 'monsterinsights_admin_footer', 1, 2 );
241
+
242
+ function monsterinsights_admin_setup_notices() {
243
+
244
+ // Don't show on MonsterInsights pages
245
+ $screen = get_current_screen();
246
+ if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) !== false ) {
247
+ return;
248
+ }
249
+
250
+ // Make sure they have the permissions to do something
251
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
252
+ return;
253
+ }
254
+
255
+ // Priority:
256
+ // 1. Google Analytics not authenticated
257
+ // 2. License key not entered for pro
258
+ // 3. License key not valid/okay for pro
259
+ // 4. WordPress + PHP min versions
260
+ // 5. (old) Optin setting not configured
261
+ // 6. Manual UA code
262
+ // 7. Automatic updates not configured
263
+ // 8. Woo upsell
264
+ // 9. EDD upsell
265
+
266
+
267
+ // 1. Google Analytics not authenticated
268
+ if ( ! is_network_admin() && ! monsterinsights_get_ua() ) {
269
+ $page = admin_url( 'admin.php?page=monsterinsights_settings' );
270
+ $message = sprintf( esc_html__( 'Please configure your %1$sGoogle Analytics settings%2$s!', 'google-analytics-for-wordpress' ),'<a href="' . $page . '">', '</a>' );
271
+ echo '<div class="error"><p>'. $message.'</p></div>';
272
+ return;
273
+ }
274
+
275
+ // 2. License key not entered for pro
276
+ $key = monsterinsights_is_pro_version() ? MonsterInsights()->license->get_license_key() : '';
277
+ if ( monsterinsights_is_pro_version() && empty( $key ) ) {
278
+ $page = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
279
+ $message = sprintf( esc_html__( 'Warning: No valid license key has been entered for MonsterInsights. You are currently not getting updates, and are not able to view reports. %1$sPlease click here to enter your license key and begin receiving updates and reports.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. esc_url( $page ) . '">', '</a>' );
280
+ echo '<div class="error"><p>'. $message.'</p></div>';
281
+ return;
282
+ }
283
+
284
+ // 3. License key not valid/okay for pro
285
+ if ( monsterinsights_is_pro_version() ) {
286
+ $message = '';
287
+ if ( MonsterInsights()->license->get_site_license_key() ){
288
+ if ( MonsterInsights()->license->site_license_expired() ) {
289
+ $message = sprintf( esc_html__( 'Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. monsterinsights_get_url( 'admin-notices', 'expired-license', "https://www.monsterinsights.com/login/" ) .'" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
290
+ } else if ( MonsterInsights()->license->site_license_disabled() ) {
291
+ $message = esc_html__( 'Your license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
292
+ } else if ( MonsterInsights()->license->site_license_invalid() ) {
293
+ $message = esc_html__( 'Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
294
+ }
295
+ } else if ( MonsterInsights()->license->get_network_license_key() ) {
296
+ if ( MonsterInsights()->license->network_license_expired() ) {
297
+ $message = sprintf( esc_html__( 'Your network license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. monsterinsights_get_url( 'admin-notices', 'expired-license', "https://www.monsterinsights.com/login/" ) .'" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
298
+ } else if ( MonsterInsights()->license->network_license_disabled() ) {
299
+ $message = esc_html__( 'Your network license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
300
+ } else if ( MonsterInsights()->license->network_license_invalid() ) {
301
+ $message = esc_html__( 'Your network license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
302
+ }
303
+ }
304
+ if ( ! empty( $message ) ) {
305
+ echo '<div class="error"><p>'. $message.'</p></div>';
306
+ return;
307
+ }
308
+ }
309
+
310
+ // 4. Notices for PHP/WP version deprecations
311
+ if ( current_user_can( 'update_core' ) ) {
312
+ global $wp_version;
313
+
314
+ // PHP 5.2/5.3
315
+ if ( version_compare( phpversion(), '5.4', '<' ) ) {
316
+ $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' );
317
+ $message = sprintf( esc_html__( 'Your site is running an outdated, insecure version of PHP (%1$s), which could be putting your site at risk for being hacked.%4$sWordPress will stop supporting your PHP version in April, 2019.%4$sUpdating PHP only takes a few minutes and will make your website significantly faster and more secure.%4$s%2$sLearn more about updating PHP%3$s', 'google-analytics-for-wordpress' ), phpversion(), '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
318
+ echo '<div class="error"><p>'. $message.'</p></div>';
319
+ return;
320
+ }
321
+ // WordPress 3.0 - 4.5
322
+ else if ( version_compare( $wp_version, '4.6', '<' ) ) {
323
+ $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' );
324
+ $message = sprintf( esc_html__( 'Your site is running an outdated version of WordPress (%1$s).%4$sMonsterInsights will stop supporting WordPress versions lower than 4.6 in April, 2019.%4$sUpdating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install.%4$s%2$sLearn more about updating WordPress%3$s', 'google-analytics-for-wordpress' ), $wp_version, '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
325
+ echo '<div class="error"><p>'. $message.'</p></div>';
326
+ return;
327
+ }
328
+ // PHP 5.4/5.5
329
+ // else if ( version_compare( phpversion(), '5.6', '<' ) ) {
330
+ // $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' );
331
+ // $message = sprintf( esc_html__( 'Your site is running an outdated, insecure version of PHP (%1$s), which could be putting your site at risk for being hacked.%4$sWordPress will stop supporting your PHP version in April, 2019.%4$sUpdating PHP only takes a few minutes and will make your website significantly faster and more secure.%4$s%2$sLearn more about updating PHP%3$s', 'google-analytics-for-wordpress' ), phpversion(), '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
332
+ // echo '<div class="error"><p>'. $message.'</p></div>';
333
+ // return;
334
+ // }
335
+ // // WordPress 4.6 - 4.8
336
+ // else if ( version_compare( $wp_version, '4.9', '<' ) ) {
337
+ // $url = monsterinsights_get_url( 'global-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' );
338
+ // $message = sprintf( esc_html__( 'Your site is running an outdated version of WordPress (%1$s).%4$sMonsterInsights will stop supporting WordPress versions lower than 4.9 in October, 2019.%4$sUpdating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install.%4$s%2$sLearn more about updating WordPress%3$s', 'google-analytics-for-wordpress' ), $wp_version, '<a href="' . $url . '" target="_blank">', '</a>', '<br>' );
339
+ // echo '<div class="error"><p>'. $message.'</p></div>';
340
+ // return;
341
+ // }
342
+ }
343
+
344
+ // 5. Optin setting not configured
345
+ // if ( ! is_network_admin() ) {
346
+ // if ( ! get_option( 'monsterinsights_tracking_notice' ) ) {
347
+ // if ( ! monsterinsights_get_option( 'anonymous_data', false ) ) {
348
+ // if ( ! monsterinsights_is_dev_url( network_site_url( '/' ) ) ) {
349
+ // if ( monsterinsights_is_pro_version() ) {
350
+ // monsterinsights_update_option( 'anonymous_data', 1 );
351
+ // return;
352
+ // }
353
+ // $optin_url = add_query_arg( 'mi_action', 'opt_into_tracking' );
354
+ // $optout_url = add_query_arg( 'mi_action', 'opt_out_of_tracking' );
355
+ // echo '<div class="updated"><p>';
356
+ // echo esc_html__( 'Allow MonsterInsights to track plugin usage? Opt-in to tracking and our newsletter to stay informed of the latest changes to MonsterInsights and help us ensure compatibility.', 'google-analytics-for-wordpress' );
357
+ // echo '&nbsp;<a href="' . esc_url( $optin_url ) . '" class="button-secondary">' . __( 'Allow', 'google-analytics-for-wordpress' ) . '</a>';
358
+ // echo '&nbsp;<a href="' . esc_url( $optout_url ) . '" class="button-secondary">' . __( 'Do not allow', 'google-analytics-for-wordpress' ) . '</a>';
359
+ // echo '</p></div>';
360
+ // return;
361
+ // } else {
362
+ // // is testing site
363
+ // update_option( 'monsterinsights_tracking_notice', '1' );
364
+ // }
365
+ // }
366
+ // }
367
+ // }
368
+
369
+ $notices = get_option( 'monsterinsights_notices' );
370
+ if ( ! is_array( $notices ) ) {
371
+ $notices = array();
372
+ }
373
+
374
+ // 6. Authenticate, not manual
375
+ $authed = MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed();
376
+ $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
377
+
378
+ if ( empty( $authed ) && ! isset( $notices['monsterinsights_auth_not_manual' ] ) ) {
379
+ echo '<div class="notice notice-info is-dismissible monsterinsights-notice" data-notice="monsterinsights_auth_not_manual">';
380
+ echo '<p>';
381
+ echo sprintf( esc_html__( 'Important: You are currently using manual UA code output. We highly recommend %1$sauthenticating with MonsterInsights%2$s so that you can access our new reporting area and take advantage of new MonsterInsights features.', 'google-analytics-for-wordpress' ), '<a href="' . $url .'">', '</a>' );
382
+ echo '</p>';
383
+ echo '</div>';
384
+ return;
385
+ }
386
+
387
+ // 7. Automatic updates not configured
388
+ // if ( ! is_network_admin() ) {
389
+ // $updates = monsterinsights_get_option( 'automatic_updates', false );
390
+ // $url = admin_url( 'admin.php?page=monsterinsights_settings' );
391
+
392
+ // if ( empty( $updates) && ! isset( $notices['monsterinsights_automatic_updates' ] ) ) {
393
+ // echo '<div class="notice notice-info is-dismissible monsterinsights-notice" data-notice="monsterinsights_automatic_updates">';
394
+ // echo '<p>';
395
+ // echo sprintf( esc_html__( 'Important: Please %1$sconfigure the Automatic Updates Settings%2$s in MonsterInsights.', 'google-analytics-for-wordpress' ), '<a href="' . $url .'">', '</a>' );
396
+ // echo '</p>';
397
+ // echo '</div>';
398
+ // return;
399
+ // }
400
+ // }
401
+
402
+ // 8. WooUpsell
403
+ if ( ! monsterinsights_is_pro_version() && class_exists( 'WooCommerce' ) ) {
404
+ if ( ! isset( $notices['monsterinsights_woocommerce_tracking_available' ] ) ) {
405
+ echo '<div class="notice notice-success is-dismissible monsterinsights-notice monsterinsights-wooedd-upsell-row" data-notice="monsterinsights_woocommerce_tracking_available">';
406
+ echo '<div class="monsterinsights-wooedd-upsell-left">';
407
+ echo '<p><strong>';
408
+ echo esc_html( 'Enhanced Ecommerce Analytics for Your WooCommerce Store', 'google-analytics-for-wordpress' );
409
+ echo '</strong></p>';
410
+ echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-small" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
411
+ echo '<p>';
412
+ echo esc_html( 'MonsterInsights Pro gives you detailed stats and insights about your customers.', 'google-analytics-for-wordpress' );
413
+ echo '</p>';
414
+ echo '<p>';
415
+ echo esc_html( 'This helps you make data-driven decisions about your content, and marketing strategy so you can increase your website traffic, leads, and sales.', 'google-analytics-for-wordpress' );
416
+ echo '</p>';
417
+ echo '<p>';
418
+ echo esc_html( 'Pro customers also get Form Tracking, Custom Dimensions Tracking, UserID Tracking and much more.', 'google-analytics-for-wordpress' );
419
+ echo '</p>';
420
+ echo '<p>';
421
+ echo esc_html( 'Start making data-driven decisions to grow your business.', 'google-analytics-for-wordpress' );
422
+ echo '</p>';
423
+ echo sprintf( esc_html__( '%1$sGet MonsterInsights Pro%2$s', 'google-analytics-for-wordpress' ), '<a class="button button-primary button-hero" href="'. monsterinsights_get_upgrade_link( 'admin-notices', 'woocommerce-upgrade' ) .'">', ' &raquo;</a>' );
424
+ echo '</p>';
425
+ echo '</div><div class="monsterinsights-wooedd-upsell-right">';
426
+ echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-large" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
427
+ echo '</div>';
428
+ echo '</div>';
429
+ return;
430
+ }
431
+ }
432
+
433
+ // 9. EDDUpsell
434
+ if ( ! monsterinsights_is_pro_version() && class_exists( 'Easy_Digital_Downloads' ) ) {
435
+ if ( ! isset( $notices['monsterinsights_edd_tracking_available' ] ) ) {
436
+ echo '<div class="notice notice-success is-dismissible monsterinsights-notice monsterinsights-wooedd-upsell-row" data-notice="monsterinsights_edd_tracking_available">';
437
+ echo '<div class="monsterinsights-wooedd-upsell-left">';
438
+ echo '<p><strong>';
439
+ echo esc_html( 'Enhanced Ecommerce Analytics for Your Easy Digital Downloads Store', 'google-analytics-for-wordpress' );
440
+ echo '</strong></p>';
441
+ echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-small" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
442
+ echo '<p>';
443
+ echo esc_html( 'MonsterInsights Pro gives you detailed stats and insights about your customers.', 'google-analytics-for-wordpress' );
444
+ echo '</p>';
445
+ echo '<p>';
446
+ echo esc_html( 'This helps you make data-driven decisions about your content, and marketing strategy so you can increase your website traffic, leads, and sales.', 'google-analytics-for-wordpress' );
447
+ echo '</p>';
448
+ echo '<p>';
449
+ echo esc_html( 'Pro customers also get Form Tracking, Custom Dimensions Tracking, UserID Tracking and much more.', 'google-analytics-for-wordpress' );
450
+ echo '</p>';
451
+ echo '<p>';
452
+ echo esc_html( 'Start making data-driven decisions to grow your business.', 'google-analytics-for-wordpress' );
453
+ echo '</p>';
454
+ echo sprintf( esc_html__( '%1$sGet MonsterInsights Pro%2$s', 'google-analytics-for-wordpress' ), '<a class="button button-primary button-hero" href="'. monsterinsights_get_upgrade_link( 'admin-notices', 'edd-upgrade' ) .'">', ' &raquo;</a>' );
455
+ echo '</p>';
456
+ echo '</div><div class="monsterinsights-wooedd-upsell-right">';
457
+ echo '<img class="monsterinsights-wooedd-upsell-image monsterinsights-wooedd-upsell-image-large" src="' . trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ) . 'assets/images/upsell/woo-edd-upsell.png">';
458
+ echo '</div>';
459
+ echo '</div>';
460
+ return;
461
+ }
462
+ }
463
+
464
+ if ( isset( $notices['monsterinsights_cross_domains_extracted'] ) && false === $notices['monsterinsights_cross_domains_extracted'] ) {
465
+ $page = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
466
+ $page = $page . '#/advanced';
467
+ $message = sprintf( esc_html__( 'Warning: MonsterInsights found cross-domain settings in the custom code field and converted them to the new settings structure. %1$sPlease click here to review and remove the code no longer needed.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. esc_url( $page ) . '">', '</a>' );
468
+ echo '<div class="notice notice-success is-dismissible monsterinsights-notice" data-notice="monsterinsights_cross_domains_extracted"><p>'. $message.'</p></div>';
469
+ return;
470
+ }
471
+ }
472
+ add_action( 'admin_notices', 'monsterinsights_admin_setup_notices' );
473
+ add_action( 'network_admin_notices', 'monsterinsights_admin_setup_notices' );
474
+
475
+
476
+ // AM Notices
477
+ function monsterinsights_am_notice_optout( $super_admin ) {
478
+ if ( monsterinsights_get_option( 'hide_am_notices', false ) || monsterinsights_get_option( 'network_hide_am_notices', false ) ) {
479
+ return false;
480
+ }
481
+ return $super_admin;
482
+ }
483
+ add_filter( "am_notifications_display", 'monsterinsights_am_notice_optout', 10, 1 );
 
 
includes/admin/ajax.php CHANGED
@@ -1,209 +1,209 @@
1
- <?php
2
- /**
3
- * Handles all admin ajax interactions for the MonsterInsights plugin.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Ajax
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- /**
18
- * Stores a user setting for the logged in WordPress User
19
- *
20
- * @access public
21
- * @since 6.0.0
22
- */
23
- function monsterinsights_ajax_set_user_setting() {
24
-
25
- // Run a security check first.
26
- check_ajax_referer( 'monsterinsights-set-user-setting', 'nonce' );
27
-
28
- // Prepare variables.
29
- $name = stripslashes( $_POST['name'] );
30
- $value = stripslashes( $_POST['value'] );
31
-
32
- // Set user setting.
33
- set_user_setting( $name, $value );
34
-
35
- // Send back the response.
36
- wp_send_json_success();
37
- wp_die();
38
-
39
- }
40
- add_action( 'wp_ajax_monsterinsights_install_addon', 'monsterinsights_ajax_install_addon' );
41
-
42
- /**
43
- * Installs a MonsterInsights addon.
44
- *
45
- * @access public
46
- * @since 6.0.0
47
- */
48
- function monsterinsights_ajax_install_addon() {
49
-
50
- // Run a security check first.
51
- check_ajax_referer( 'monsterinsights-install', 'nonce' );
52
-
53
- if ( ! current_user_can( 'install_plugins' ) ) {
54
- echo json_encode( true );
55
- }
56
-
57
- // Install the addon.
58
- if ( isset( $_POST['plugin'] ) ) {
59
- $download_url = $_POST['plugin'];
60
- global $hook_suffix;
61
-
62
- // Set the current screen to avoid undefined notices.
63
- set_current_screen();
64
-
65
- // Prepare variables.
66
- $method = '';
67
- $url = add_query_arg(
68
- array(
69
- 'page' => 'monsterinsights-settings'
70
- ),
71
- admin_url( 'admin.php' )
72
- );
73
- $url = esc_url( $url );
74
-
75
- // Start output bufferring to catch the filesystem form if credentials are needed.
76
- ob_start();
77
- if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
78
- $form = ob_get_clean();
79
- echo json_encode( array( 'form' => $form ) );
80
- wp_die();
81
- }
82
-
83
- // If we are not authenticated, make it happen now.
84
- if ( ! WP_Filesystem( $creds ) ) {
85
- ob_start();
86
- request_filesystem_credentials( $url, $method, true, false, null );
87
- $form = ob_get_clean();
88
- echo json_encode( array( 'form' => $form ) );
89
- wp_die();
90
- }
91
-
92
- // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
93
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
94
- $base = MonsterInsights();
95
- require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin.php';
96
-
97
- // Create the plugin upgrader with our custom skin.
98
- $installer = new Plugin_Upgrader( $skin = new MonsterInsights_Skin() );
99
- $installer->install( $download_url );
100
-
101
- // Flush the cache and return the newly installed plugin basename.
102
- wp_cache_flush();
103
- if ( $installer->plugin_info() ) {
104
- $plugin_basename = $installer->plugin_info();
105
- echo json_encode( array( 'plugin' => $plugin_basename ) );
106
- wp_die();
107
- }
108
- }
109
-
110
- // Send back a response.
111
- echo json_encode( true );
112
- wp_die();
113
-
114
- }
115
-
116
- add_action( 'wp_ajax_monsterinsights_activate_addon', 'monsterinsights_ajax_activate_addon' );
117
- /**
118
- * Activates a MonsterInsights addon.
119
- *
120
- * @access public
121
- * @since 6.0.0
122
- */
123
- function monsterinsights_ajax_activate_addon() {
124
-
125
- // Run a security check first.
126
- check_ajax_referer( 'monsterinsights-activate', 'nonce' );
127
-
128
- if ( ! current_user_can( 'activate_plugins' ) ) {
129
- echo json_encode( true );
130
- }
131
-
132
- // Activate the addon.
133
- if ( isset( $_POST['plugin'] ) ) {
134
- if ( isset( $_POST['isnetwork'] ) && $_POST['isnetwork'] ) {
135
- $activate = activate_plugin( $_POST['plugin'], NULL, true );
136
- } else {
137
- $activate = activate_plugin( $_POST['plugin'] );
138
- }
139
-
140
- if ( is_wp_error( $activate ) ) {
141
- echo json_encode( array( 'error' => $activate->get_error_message() ) );
142
- wp_die();
143
- }
144
- }
145
-
146
- echo json_encode( true );
147
- wp_die();
148
-
149
- }
150
-
151
- add_action( 'wp_ajax_monsterinsights_deactivate_addon', 'monsterinsights_ajax_deactivate_addon' );
152
- /**
153
- * Deactivates a MonsterInsights addon.
154
- *
155
- * @access public
156
- * @since 6.0.0
157
- */
158
- function monsterinsights_ajax_deactivate_addon() {
159
-
160
- // Run a security check first.
161
- check_ajax_referer( 'monsterinsights-deactivate', 'nonce' );
162
-
163
- if ( ! current_user_can( 'activate_plugins' ) ) {
164
- echo json_encode( true );
165
- }
166
-
167
- // Deactivate the addon.
168
- if ( isset( $_POST['plugin'] ) ) {
169
- if ( isset( $_POST['isnetwork'] ) && $_POST['isnetwork'] ) {
170
- $deactivate = deactivate_plugins( $_POST['plugin'], false, true );
171
- } else {
172
- $deactivate = deactivate_plugins( $_POST['plugin'] );
173
- }
174
- }
175
-
176
- echo json_encode( true );
177
- wp_die();
178
- }
179
-
180
- /**
181
- * Called whenever a notice is dismissed in MonsterInsights or its Addons.
182
- *
183
- * Updates a key's value in the options table to mark the notice as dismissed,
184
- * preventing it from displaying again
185
- *
186
- * @access public
187
- * @since 6.0.0
188
- */
189
- function monsterinsights_ajax_dismiss_notice() {
190
-
191
- // Run a security check first.
192
- check_ajax_referer( 'monsterinsights-dismiss-notice', 'nonce' );
193
-
194
- // Deactivate the notice
195
- if ( isset( $_POST['notice'] ) ) {
196
- // Init the notice class and mark notice as deactivated
197
- MonsterInsights()->notices->dismiss( $_POST['notice'] );
198
-
199
- // Return true
200
- echo json_encode( true );
201
- wp_die();
202
- }
203
-
204
- // If here, an error occurred
205
- echo json_encode( false );
206
- wp_die();
207
-
208
- }
209
  add_action( 'wp_ajax_monsterinsights_ajax_dismiss_notice', 'monsterinsights_ajax_dismiss_notice' );
1
+ <?php
2
+ /**
3
+ * Handles all admin ajax interactions for the MonsterInsights plugin.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Ajax
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ /**
18
+ * Stores a user setting for the logged in WordPress User
19
+ *
20
+ * @access public
21
+ * @since 6.0.0
22
+ */
23
+ function monsterinsights_ajax_set_user_setting() {
24
+
25
+ // Run a security check first.
26
+ check_ajax_referer( 'monsterinsights-set-user-setting', 'nonce' );
27
+
28
+ // Prepare variables.
29
+ $name = stripslashes( $_POST['name'] );
30
+ $value = stripslashes( $_POST['value'] );
31
+
32
+ // Set user setting.
33
+ set_user_setting( $name, $value );
34
+
35
+ // Send back the response.
36
+ wp_send_json_success();
37
+ wp_die();
38
+
39
+ }
40
+ add_action( 'wp_ajax_monsterinsights_install_addon', 'monsterinsights_ajax_install_addon' );
41
+
42
+ /**
43
+ * Installs a MonsterInsights addon.
44
+ *
45
+ * @access public
46
+ * @since 6.0.0
47
+ */
48
+ function monsterinsights_ajax_install_addon() {
49
+
50
+ // Run a security check first.
51
+ check_ajax_referer( 'monsterinsights-install', 'nonce' );
52
+
53
+ if ( ! current_user_can( 'install_plugins' ) ) {
54
+ echo json_encode( true );
55
+ }
56
+
57
+ // Install the addon.
58
+ if ( isset( $_POST['plugin'] ) ) {
59
+ $download_url = $_POST['plugin'];
60
+ global $hook_suffix;
61
+
62
+ // Set the current screen to avoid undefined notices.
63
+ set_current_screen();
64
+
65
+ // Prepare variables.
66
+ $method = '';
67
+ $url = add_query_arg(
68
+ array(
69
+ 'page' => 'monsterinsights-settings'
70
+ ),
71
+ admin_url( 'admin.php' )
72
+ );
73
+ $url = esc_url( $url );
74
+
75
+ // Start output bufferring to catch the filesystem form if credentials are needed.
76
+ ob_start();
77
+ if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
78
+ $form = ob_get_clean();
79
+ echo json_encode( array( 'form' => $form ) );
80
+ wp_die();
81
+ }
82
+
83
+ // If we are not authenticated, make it happen now.
84
+ if ( ! WP_Filesystem( $creds ) ) {
85
+ ob_start();
86
+ request_filesystem_credentials( $url, $method, true, false, null );
87
+ $form = ob_get_clean();
88
+ echo json_encode( array( 'form' => $form ) );
89
+ wp_die();
90
+ }
91
+
92
+ // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
93
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
94
+ $base = MonsterInsights();
95
+ require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin.php';
96
+
97
+ // Create the plugin upgrader with our custom skin.
98
+ $installer = new Plugin_Upgrader( $skin = new MonsterInsights_Skin() );
99
+ $installer->install( $download_url );
100
+
101
+ // Flush the cache and return the newly installed plugin basename.
102
+ wp_cache_flush();
103
+ if ( $installer->plugin_info() ) {
104
+ $plugin_basename = $installer->plugin_info();
105
+ echo json_encode( array( 'plugin' => $plugin_basename ) );
106
+ wp_die();
107
+ }
108
+ }
109
+
110
+ // Send back a response.
111
+ echo json_encode( true );
112
+ wp_die();
113
+
114
+ }
115
+
116
+ add_action( 'wp_ajax_monsterinsights_activate_addon', 'monsterinsights_ajax_activate_addon' );
117
+ /**
118
+ * Activates a MonsterInsights addon.
119
+ *
120
+ * @access public
121
+ * @since 6.0.0
122
+ */
123
+ function monsterinsights_ajax_activate_addon() {
124
+
125
+ // Run a security check first.
126
+ check_ajax_referer( 'monsterinsights-activate', 'nonce' );
127
+
128
+ if ( ! current_user_can( 'activate_plugins' ) ) {
129
+ echo json_encode( true );
130
+ }
131
+
132
+ // Activate the addon.
133
+ if ( isset( $_POST['plugin'] ) ) {
134
+ if ( isset( $_POST['isnetwork'] ) && $_POST['isnetwork'] ) {
135
+ $activate = activate_plugin( $_POST['plugin'], NULL, true );
136
+ } else {
137
+ $activate = activate_plugin( $_POST['plugin'] );
138
+ }
139
+
140
+ if ( is_wp_error( $activate ) ) {
141
+ echo json_encode( array( 'error' => $activate->get_error_message() ) );
142
+ wp_die();
143
+ }
144
+ }
145
+
146
+ echo json_encode( true );
147
+ wp_die();
148
+
149
+ }
150
+
151
+ add_action( 'wp_ajax_monsterinsights_deactivate_addon', 'monsterinsights_ajax_deactivate_addon' );
152
+ /**
153
+ * Deactivates a MonsterInsights addon.
154
+ *
155
+ * @access public
156
+ * @since 6.0.0
157
+ */
158
+ function monsterinsights_ajax_deactivate_addon() {
159
+
160
+ // Run a security check first.
161
+ check_ajax_referer( 'monsterinsights-deactivate', 'nonce' );
162
+
163
+ if ( ! current_user_can( 'activate_plugins' ) ) {
164
+ echo json_encode( true );
165
+ }
166
+
167
+ // Deactivate the addon.
168
+ if ( isset( $_POST['plugin'] ) ) {
169
+ if ( isset( $_POST['isnetwork'] ) && $_POST['isnetwork'] ) {
170
+ $deactivate = deactivate_plugins( $_POST['plugin'], false, true );
171
+ } else {
172
+ $deactivate = deactivate_plugins( $_POST['plugin'] );
173
+ }
174
+ }
175
+
176
+ echo json_encode( true );
177
+ wp_die();
178
+ }
179
+
180
+ /**
181
+ * Called whenever a notice is dismissed in MonsterInsights or its Addons.
182
+ *
183
+ * Updates a key's value in the options table to mark the notice as dismissed,
184
+ * preventing it from displaying again
185
+ *
186
+ * @access public
187
+ * @since 6.0.0
188
+ */
189
+ function monsterinsights_ajax_dismiss_notice() {
190
+
191
+ // Run a security check first.
192
+ check_ajax_referer( 'monsterinsights-dismiss-notice', 'nonce' );
193
+
194
+ // Deactivate the notice
195
+ if ( isset( $_POST['notice'] ) ) {
196
+ // Init the notice class and mark notice as deactivated
197
+ MonsterInsights()->notices->dismiss( $_POST['notice'] );
198
+
199
+ // Return true
200
+ echo json_encode( true );
201
+ wp_die();
202
+ }
203
+
204
+ // If here, an error occurred
205
+ echo json_encode( false );
206
+ wp_die();
207
+
208
+ }
209
  add_action( 'wp_ajax_monsterinsights_ajax_dismiss_notice', 'monsterinsights_ajax_dismiss_notice' );
includes/admin/api-auth.php CHANGED
@@ -1,575 +1,583 @@
1
- <?php
2
- /**
3
- * Google Client admin class.
4
- *
5
- * Handles retrieving whether a particular notice has been dismissed or not,
6
- * as well as marking a notice as dismissed.
7
- *
8
- * @since 7.0.0
9
- *
10
- * @package MonsterInsights
11
- * @subpackage GA Client
12
- * @author Chris Christoff
13
- */
14
-
15
- // Exit if accessed directly
16
- if ( ! defined( 'ABSPATH' ) ) {
17
- exit;
18
- }
19
-
20
- final class MonsterInsights_API_Auth {
21
-
22
- /**
23
- * Primary class constructor.
24
- *
25
- * @access public
26
- * @since 7.0.0
27
- */
28
- public function __construct() {
29
-
30
- // Authentication Actions
31
- add_action( 'wp_ajax_monsterinsights_maybe_authenticate', array( $this, 'maybe_authenticate' ) );
32
- add_action( 'wp_ajax_monsterinsights_maybe_reauthenticate', array( $this, 'maybe_reauthenticate' ) );
33
- add_action( 'wp_ajax_monsterinsights_maybe_verify', array( $this, 'maybe_verify' ) );
34
- add_action( 'wp_ajax_monsterinsights_maybe_delete', array( $this, 'maybe_delete' ) );
35
-
36
- add_action( 'admin_init', array( $this, 'authenticate_listener' ) );
37
- add_action( 'admin_init', array( $this, 'reauthenticate_listener' ) );
38
-
39
- add_action( 'wp_ajax_nopriv_monsterinsights_is_installed', array( $this, 'is_installed' ) );
40
- add_action( 'wp_ajax_nopriv_monsterinsights_rauthenticate', array( $this, 'rauthenticate' ) );
41
-
42
- add_filter( 'monsterinsights_maybe_authenticate_siteurl', array( $this, 'before_redirect' ) );
43
- }
44
-
45
- public function get_tt(){
46
- $tt = is_network_admin() ? get_site_option( 'monsterinsights_network_tt', '' ) : get_option( 'monsterinsights_site_tt', '' );
47
- if ( empty( $tt ) ) {
48
- // if TT is empty, generate a new one, save it and then return it
49
- $tt = $this->generate_tt();
50
- $this->is_network_admin() ? update_site_option( 'monsterinsights_network_tt', $tt ) : update_option( 'monsterinsights_site_tt', $tt );
51
- }
52
- return $tt;
53
- }
54
-
55
- public function rotate_tt(){
56
- $tt = $this->generate_tt();
57
- is_network_admin() ? update_site_option( 'monsterinsights_network_tt', $tt ) : update_option( 'monsterinsights_site_tt', $tt );
58
- }
59
-
60
- public function generate_tt(){
61
- return hash( 'sha512', wp_generate_password( 128, true, true ) . AUTH_SALT . uniqid( "", true ) );
62
- }
63
-
64
- public function validate_tt( $passed_tt = '' ) {
65
- $tt = $this->get_tt();
66
- return hash_equals( $tt, $passed_tt );
67
- }
68
-
69
- public function is_installed() {
70
- wp_send_json_success(
71
- array(
72
- 'version' => MONSTERINSIGHTS_VERSION,
73
- 'pro' => monsterinsights_is_pro_version(),
74
- )
75
- );
76
- }
77
-
78
- public function maybe_authenticate(){
79
-
80
- // Check nonce
81
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
82
-
83
- // current user can authenticate
84
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
85
- wp_send_json_error( array( 'message' => __( "You don't have permission to authenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
86
- }
87
-
88
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
89
- define( 'WP_NETWORK_ADMIN', true );
90
- }
91
-
92
- // Only for Pro users, require a license key to be entered first so we can link to things.
93
- $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
94
- if ( monsterinsights_is_pro_version() && ! $valid ) {
95
- wp_send_json_error( array( 'message' => __( "Cannot authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
96
- }
97
-
98
- // we do not have a current auth
99
- if ( ! $this->is_network_admin() && MonsterInsights()->auth->is_authed() ) {
100
- wp_send_json_error( array( 'message' => __( "Cannot authenticate. Please re-authenticate.", 'google-analytics-for-wordpress' ) ) );
101
- } else if ( $this->is_network_admin() && MonsterInsights()->auth->is_network_authed() ) {
102
- wp_send_json_error( array( 'message' => __( "Cannot network authenticate. Please re-authenticate on the network settings panel.", 'google-analytics-for-wordpress' ) ) );
103
- }
104
-
105
- $sitei = $this->get_sitei();
106
- //update_network_option( get_current_network_id(), 'monsterinsights_network_sitei', $sitei );
107
-
108
- $siteurl = add_query_arg( array(
109
- 'tt' => $this->get_tt(),
110
- 'sitei' => $sitei,
111
- 'miversion' => MONSTERINSIGHTS_VERSION,
112
- 'ajaxurl' => admin_url( 'admin-ajax.php' ),
113
- 'network' => is_network_admin() ? 'network' : 'site',
114
- 'siteurl' => is_network_admin() ? network_admin_url() : site_url(),
115
- 'return' => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
116
- 'testurl' => 'https://api.monsterinsights.com/v2/test/',
117
- ), $this->get_route( 'https://' . monsterinsights_get_api_url() . 'auth/new/{type}' ) );
118
-
119
- if ( monsterinsights_is_pro_version() ) {
120
- $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
121
- $siteurl = add_query_arg( 'license', $key, $siteurl );
122
- }
123
-
124
- $siteurl = apply_filters( 'monsterinsights_maybe_authenticate_siteurl', $siteurl );
125
- wp_send_json_success( array( 'redirect' => $siteurl ) );
126
- }
127
-
128
- public function rauthenticate() {
129
- // Check for missing params
130
- $reqd_args = array( 'key', 'token', 'ua', 'miview', 'a', 'w', 'p', 'tt', 'network' );
131
- foreach ( $reqd_args as $arg ) {
132
- if ( empty( $_REQUEST[$arg] ) ) {
133
- wp_send_json_error(
134
- array(
135
- 'error' => 'authenticate_missing_arg',
136
- 'message' => 'Authenticate missing parameter: ' . $arg,
137
- 'version' => MONSTERINSIGHTS_VERSION,
138
- 'pro' => monsterinsights_is_pro_version(),
139
- )
140
- );
141
- }
142
- }
143
-
144
- if ( ! empty( $_REQUEST['network'] ) && 'network' === $_REQUEST['network'] ) {
145
- define( 'WP_NETWORK_ADMIN', true );
146
- }
147
-
148
- if ( ! $this->validate_tt( $_REQUEST['tt'] ) ) {
149
- wp_send_json_error(
150
- array(
151
- 'error' => 'authenticate_invalid_tt',
152
- 'message' => 'Invalid TT sent',
153
- 'version' => MONSTERINSIGHTS_VERSION,
154
- 'pro' => monsterinsights_is_pro_version(),
155
- )
156
- );
157
- }
158
-
159
- // If the tt is validated, send a success response to trigger the regular auth process.
160
- wp_send_json_success();
161
- }
162
-
163
- public function authenticate_listener(){
164
- // Make sure it's for us
165
- if ( empty( $_REQUEST['mi-oauth-action'] ) || $_REQUEST['mi-oauth-action'] !== 'auth' ) {
166
- return;
167
- }
168
-
169
- // User can authenticate
170
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
171
- return;
172
- }
173
-
174
- // Invalid request
175
- if ( empty( $_REQUEST['tt'] ) || ! $this->validate_tt( $_REQUEST['tt'] ) ) {
176
- return;
177
- }
178
-
179
- // Make sure has required params
180
- if ( empty( $_REQUEST['key'] ) ||
181
- empty( $_REQUEST['token'] ) ||
182
- empty( $_REQUEST['ua'] ) ||
183
- empty( $_REQUEST['miview'] ) ||
184
- empty( $_REQUEST['a'] ) ||
185
- empty( $_REQUEST['w'] ) ||
186
- empty( $_REQUEST['p'] )
187
- ) {
188
- return;
189
- }
190
-
191
- // Invalid UA code
192
- $ua = monsterinsights_is_valid_ua( $_REQUEST['ua'] );
193
- if ( empty( $ua ) ) {
194
- return;
195
- }
196
-
197
- $profile = array(
198
- 'key' => sanitize_text_field( $_REQUEST['key'] ),
199
- 'token' => sanitize_text_field( $_REQUEST['token'] ),
200
- 'ua' => monsterinsights_is_valid_ua( $_REQUEST['ua'] ),
201
- 'viewname' => sanitize_text_field( $_REQUEST['miview'] ),
202
- 'a' => sanitize_text_field( $_REQUEST['a'] ), // AccountID
203
- 'w' => sanitize_text_field( $_REQUEST['w'] ), // PropertyID
204
- 'p' => sanitize_text_field( $_REQUEST['p'] ), // View ID
205
- 'siteurl' => site_url(),
206
- 'neturl' => network_admin_url(),
207
- );
208
-
209
- $worked = $this->verify_auth( $profile );
210
- if ( ! $worked || is_wp_error( $worked ) ) {
211
- return;
212
- }
213
-
214
- // Save Profile
215
- $this->is_network_admin() ? MonsterInsights()->auth->set_network_analytics_profile( $profile ) : MonsterInsights()->auth->set_analytics_profile( $profile );
216
-
217
- // Clear cache
218
- $where = $this->is_network_admin() ? 'network' : 'site';
219
- MonsterInsights()->reporting->delete_aggregate_data( $where );
220
-
221
- $url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ) ;
222
- $url = add_query_arg( array(
223
- 'mi_action' => 'auth',
224
- 'success' => 'true',
225
- ), $url );
226
- $url = apply_filters( 'monsterinsights_auth_success_redirect_url', $url );
227
- wp_safe_redirect( $url );
228
- exit;
229
- }
230
-
231
- public function maybe_reauthenticate(){
232
-
233
- // Check nonce
234
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
235
-
236
- // current user can authenticate
237
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
238
- wp_send_json_error( array( 'message' => __( "You don't have permission to re-authenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
239
- }
240
-
241
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
242
- define( 'WP_NETWORK_ADMIN', true );
243
- }
244
-
245
- // Only for Pro users, require a license key to be entered first so we can link to things.
246
- $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
247
- if ( monsterinsights_is_pro_version() && ! $valid ) {
248
- wp_send_json_error( array( 'message' => __( "Cannot re-authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
249
- }
250
-
251
- // we do have a current auth
252
- if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
253
- wp_send_json_error( array( 'message' => __( "Cannot re-authenticate. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
254
- } else if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
255
- wp_send_json_error( array( 'message' => __( "Cannot re-authenticate the network. Please authenticate on the network settings panel.", 'google-analytics-for-wordpress' ) ) );
256
- }
257
-
258
- $siteurl = add_query_arg( array(
259
- 'tt' => $this->get_tt(),
260
- 'sitei' => $this->get_sitei(),
261
- 'miversion' => MONSTERINSIGHTS_VERSION,
262
- 'ajaxurl' => admin_url( 'admin-ajax.php' ),
263
- 'network' => is_network_admin() ? 'network' : 'site',
264
- 'siteurl' => is_network_admin() ? network_admin_url() : site_url(),
265
- 'key' => MonsterInsights()->auth->get_key(),
266
- 'token' => MonsterInsights()->auth->get_token(),
267
- 'return' => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
268
- 'testurl' => 'https://api.monsterinsights.com/v2/test/',
269
- ), $this->get_route( 'https://' . monsterinsights_get_api_url() . 'auth/reauth/{type}' ) );
270
-
271
- if ( monsterinsights_is_pro_version() ) {
272
- $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
273
- $siteurl = add_query_arg( 'license', $key, $siteurl );
274
- }
275
-
276
- $siteurl = apply_filters( 'monsterinsights_maybe_authenticate_siteurl', $siteurl );
277
-
278
- wp_send_json_success( array( 'redirect' => $siteurl ) );
279
- }
280
-
281
- public function reauthenticate_listener(){
282
- // Make sure it's for us
283
- if ( empty( $_REQUEST['mi-oauth-action'] ) || $_REQUEST['mi-oauth-action'] !== 'reauth' ) {
284
- return;
285
- }
286
-
287
- // User can authenticate
288
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
289
- return;
290
- }
291
-
292
- // Invalid request
293
- if ( empty( $_REQUEST['tt'] ) || ! $this->validate_tt( $_REQUEST['tt'] ) ) {
294
- return;
295
- }
296
-
297
- // Make sure has required params
298
- if (
299
- empty( $_REQUEST['ua'] ) ||
300
- empty( $_REQUEST['miview'] ) ||
301
- empty( $_REQUEST['a'] ) ||
302
- empty( $_REQUEST['w'] ) ||
303
- empty( $_REQUEST['p'] )
304
- ) {
305
- return;
306
- }
307
-
308
- // Invalid UA code
309
- $ua = monsterinsights_is_valid_ua( $_REQUEST['ua'] );
310
- if ( empty( $ua ) ) {
311
- return;
312
- }
313
-
314
- // we do have a current auth
315
- $existing = $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile() : MonsterInsights()->auth->get_analytics_profile();
316
- if ( empty( $existing['key'] ) || empty( $existing['token'] ) ) {
317
- return;
318
- }
319
-
320
- $profile = array(
321
- 'key' => $existing['key'],
322
- 'token' => $existing['token'],
323
- 'ua' => monsterinsights_is_valid_ua( $_REQUEST['ua'] ),
324
- 'viewname' => sanitize_text_field( $_REQUEST['miview'] ),
325
- 'a' => sanitize_text_field( $_REQUEST['a'] ),
326
- 'w' => sanitize_text_field( $_REQUEST['w'] ),
327
- 'p' => sanitize_text_field( $_REQUEST['p'] ),
328
- 'siteurl' => site_url(),
329
- 'neturl' => network_admin_url(),
330
- );
331
-
332
- // Save Profile
333
- $this->is_network_admin() ? MonsterInsights()->auth->set_network_analytics_profile( $profile ) : MonsterInsights()->auth->set_analytics_profile( $profile );
334
-
335
- // Clear cache
336
- $where = $this->is_network_admin() ? 'network' : 'site';
337
- MonsterInsights()->reporting->delete_aggregate_data( $where );
338
-
339
- $url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ) ;
340
- $url = add_query_arg( array(
341
- 'mi_action' => 'reauth',
342
- 'success' => 'true',
343
- ), $url );
344
- $url = apply_filters( 'monsterinsights_reauth_success_redirect_url', $url );
345
-
346
- wp_safe_redirect( $url );
347
- exit;
348
- }
349
-
350
- public function maybe_verify(){
351
-
352
- // Check nonce
353
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
354
-
355
- // current user can verify
356
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
357
- wp_send_json_error( array( 'message' => __( "You don't have permission to verify MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
358
- }
359
-
360
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
361
- define( 'WP_NETWORK_ADMIN', true );
362
- }
363
-
364
- // we have an auth to verify
365
- if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
366
- wp_send_json_error( array( 'message' => __( "Cannot verify. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
367
- } else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
368
- wp_send_json_error( array( 'message' => __( "Cannot verify. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
369
- }
370
-
371
- $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
372
- if ( monsterinsights_is_pro_version() && ! $valid ) {
373
- wp_send_json_error( array( 'message' => __( "Cannot verify. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
374
- }
375
-
376
- $worked = $this->verify_auth();
377
- if ( $worked && ! is_wp_error( $worked ) ) {
378
- wp_send_json_success( array( 'message' => __( "Successfully verified.", 'google-analytics-for-wordpress' ) ) );
379
- } else {
380
- wp_send_json_error( array( 'message' => __( "Could not verify.", 'google-analytics-for-wordpress' ) ) );
381
- }
382
- }
383
-
384
- public function verify_auth( $credentials = array() ){
385
- $creds = ! empty( $credentials ) ? $credentials : ( $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile( true ) : MonsterInsights()->auth->get_analytics_profile( true ) );
386
-
387
- if ( empty( $creds['key'] ) ) {
388
- return new WP_Error( 'validation-error', sprintf( __( 'Verify auth key not passed', 'google-analytics-for-wordpress' ) ) );
389
- }
390
-
391
- $network = ! empty( $_REQUEST['network'] ) ? $_REQUEST['network'] === 'network' : $this->is_network_admin();
392
- $api = new MonsterInsights_API_Request( $this->get_route( 'auth/verify/{type}/' ), array( 'network' => $network, 'tt' => $this->get_tt(), 'key' => $creds['key'], 'token' => $creds['token'], 'testurl' => 'https://api.monsterinsights.com/v2/test/' ) );
393
- $ret = $api->request();
394
-
395
- $this->rotate_tt();
396
- if ( is_wp_error( $ret ) ) {
397
- return $ret;
398
- } else {
399
- return true;
400
- }
401
- }
402
-
403
- public function maybe_delete(){
404
-
405
- // Check nonce
406
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
407
-
408
- // current user can delete
409
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
410
- wp_send_json_error( array( 'message' => __( "You don't have permission to deauthenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
411
- }
412
-
413
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
414
- define( 'WP_NETWORK_ADMIN', true );
415
- }
416
-
417
- // we have an auth to delete
418
- if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
419
- wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. You are not currently authed.", 'google-analytics-for-wordpress' ) ) );
420
- } else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
421
- wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. You are not currently authed.", 'google-analytics-for-wordpress' ) ) );
422
- }
423
-
424
- $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
425
- if ( monsterinsights_is_pro_version() && ! $valid ) {
426
- wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
427
- }
428
-
429
- $force = ! empty( $_REQUEST['forcedelete'] ) && $_REQUEST['forcedelete'] === 'true';
430
-
431
- $worked = $this->delete_auth( $force );
432
- if ( $worked && ! is_wp_error( $worked ) ) {
433
- wp_send_json_success( array( 'message' => __( "Successfully deauthenticated.", 'google-analytics-for-wordpress' ) ) );
434
- } else {
435
- if ( $force ) {
436
- wp_send_json_success( array( 'message' => __( "Successfully force deauthenticated.", 'google-analytics-for-wordpress' ) ) );
437
- } else {
438
- wp_send_json_error( array( 'message' => __( "Could not deauthenticate.", 'google-analytics-for-wordpress' ) ) );
439
- }
440
- }
441
- }
442
-
443
- public function delete_auth( $force = false ){
444
- if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
445
- return false;
446
- } else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
447
- return false;
448
- }
449
-
450
- $creds = $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile( true ) : MonsterInsights()->auth->get_analytics_profile( true );
451
-
452
- if ( empty( $creds['key'] ) ) {
453
- return false;
454
- }
455
-
456
- // If we have a new siteurl enabled option and the profile site doesn't match the current site, deactivate anyways
457
- if ( is_network_admin() ) {
458
- $siteurl = network_admin_url();
459
- if ( ! empty( $creds['neturl' ] ) && $creds['neturl'] !== $siteurl ) {
460
- MonsterInsights()->auth->delete_network_analytics_profile( true );
461
- return true;
462
- }
463
- } else {
464
- $siteurl = site_url();
465
- if ( ! empty( $creds['siteurl' ] ) && $creds['siteurl'] !== $siteurl ) {
466
- MonsterInsights()->auth->delete_analytics_profile( true );
467
- return true;
468
- }
469
- }
470
-
471
- $api = new MonsterInsights_API_Request( $this->get_route( 'auth/delete/{type}/' ), array( 'network' => $this->is_network_admin(), 'tt' => $this->get_tt(), 'key' => $creds['key'], 'token' => $creds['token'], 'testurl' => 'https://api.monsterinsights.com/v2/test/' ) );
472
- $ret = $api->request();
473
-
474
- $this->rotate_tt();
475
- if ( is_wp_error( $ret ) && ! $force ) {
476
- return false;
477
- } else {
478
- if ( $this->is_network_admin() ) {
479
- MonsterInsights()->auth->delete_network_analytics_profile( true );
480
- } else {
481
- MonsterInsights()->auth->delete_analytics_profile( true );
482
-
483
- }
484
- return true;
485
- }
486
- }
487
-
488
- /**
489
- * Function to delete network auth in the uninstall process where we can't check if is network admin.
490
- *
491
- * @return bool
492
- */
493
- public function uninstall_network_auth() {
494
-
495
- if ( ! MonsterInsights()->auth->is_network_authed() ) {
496
- return false;
497
- }
498
-
499
- $creds = MonsterInsights()->auth->get_network_analytics_profile( true );
500
-
501
- $api = new MonsterInsights_API_Request( $this->get_route( 'auth/delete/{type}/' ), array(
502
- 'network' => true,
503
- 'tt' => $this->get_tt(),
504
- 'key' => $creds['key'],
505
- 'token' => $creds['token'],
506
- 'testurl' => 'https://api.monsterinsights.com/v2/test/'
507
- ) );
508
- // Force the network admin url otherwise this will fail not finding the url in relay.
509
- $api->site_url = network_admin_url();
510
- $ret = $api->request();
511
-
512
- $this->rotate_tt();
513
- if ( is_wp_error( $ret ) ) {
514
- return false;
515
- } else {
516
- MonsterInsights()->auth->delete_network_analytics_profile( true );
517
- return true;
518
- }
519
- }
520
-
521
- public function get_type() {
522
- $base = monsterinsights_is_pro_version() ? 'pro' : 'lite';
523
- return apply_filters( 'monsterinsights_api_auth_get_type', $base );
524
- }
525
-
526
- public function get_route( $route = '' ) {
527
- $route = str_replace( '{type}', $this->get_type(), $route );
528
- $route = trailingslashit( $route );
529
- return $route;
530
- }
531
-
532
- public function is_network_admin() {
533
- return is_multisite() && is_network_admin();
534
- }
535
-
536
- public function get_sitei() {
537
- // $sitei = get_network_option( get_current_network_id(), 'monsterinsights_network_sitei', false );
538
- // if ( ! empty( $sitei ) && strlen( $sitei ) >= 1 ) {
539
- // return $sitei;
540
- // }
541
-
542
- $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
543
- $secure_auth_key = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
544
- $logged_in_key = defined( 'LOGGED_IN_KEY' ) ? LOGGED_IN_KEY : '';
545
-
546
- $sitei = $auth_key . $secure_auth_key . $logged_in_key;
547
- $sitei = preg_replace('/[^a-zA-Z0-9]/', '', $sitei );
548
- $sitei = sanitize_text_field( $sitei );
549
- $sitei = trim( $sitei );
550
- $sitei = ( strlen($sitei) > 30 ) ? substr($sitei, 0, 30 ) : $sitei;
551
- return $sitei;
552
- }
553
-
554
- /**
555
- * Logic to run before serving the redirect url during auth.
556
- *
557
- * @param string $url
558
- *
559
- * @return string
560
- */
561
- public function before_redirect( $url ) {
562
-
563
- // If Bad Behavior plugin is installed.
564
- if ( function_exists( 'bb2_read_settings' ) ) {
565
- // Make sure the offsite_forms option is enabled to allow auth.
566
- $bb_settings = get_option( 'bad_behavior_settings' );
567
- if ( empty( $bb_settings['offsite_forms'] ) || false === $bb_settings['offsite_forms'] ) {
568
- $bb_settings['offsite_forms'] = true;
569
- update_option( 'bad_behavior_settings', $bb_settings );
570
- }
571
- }
572
-
573
- return $url;
574
- }
575
- }
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Google Client admin class.
4
+ *
5
+ * Handles retrieving whether a particular notice has been dismissed or not,
6
+ * as well as marking a notice as dismissed.
7
+ *
8
+ * @since 7.0.0
9
+ *
10
+ * @package MonsterInsights
11
+ * @subpackage GA Client
12
+ * @author Chris Christoff
13
+ */
14
+
15
+ // Exit if accessed directly
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+ final class MonsterInsights_API_Auth {
21
+
22
+ /**
23
+ * Primary class constructor.
24
+ *
25
+ * @access public
26
+ * @since 7.0.0
27
+ */
28
+ public function __construct() {
29
+
30
+ // Authentication Actions
31
+ add_action( 'wp_ajax_monsterinsights_maybe_authenticate', array( $this, 'maybe_authenticate' ) );
32
+ add_action( 'wp_ajax_monsterinsights_maybe_reauthenticate', array( $this, 'maybe_reauthenticate' ) );
33
+ add_action( 'wp_ajax_monsterinsights_maybe_verify', array( $this, 'maybe_verify' ) );
34
+ add_action( 'wp_ajax_monsterinsights_maybe_delete', array( $this, 'maybe_delete' ) );
35
+
36
+ add_action( 'admin_init', array( $this, 'authenticate_listener' ) );
37
+ add_action( 'admin_init', array( $this, 'reauthenticate_listener' ) );
38
+
39
+ add_action( 'wp_ajax_nopriv_monsterinsights_is_installed', array( $this, 'is_installed' ) );
40
+ add_action( 'wp_ajax_nopriv_monsterinsights_rauthenticate', array( $this, 'rauthenticate' ) );
41
+
42
+ add_filter( 'monsterinsights_maybe_authenticate_siteurl', array( $this, 'before_redirect' ) );
43
+ }
44
+
45
+ public function get_tt(){
46
+ $tt = is_network_admin() ? get_site_option( 'monsterinsights_network_tt', '' ) : get_option( 'monsterinsights_site_tt', '' );
47
+ if ( empty( $tt ) ) {
48
+ // if TT is empty, generate a new one, save it and then return it
49
+ $tt = $this->generate_tt();
50
+ $this->is_network_admin() ? update_site_option( 'monsterinsights_network_tt', $tt ) : update_option( 'monsterinsights_site_tt', $tt );
51
+ }
52
+ return $tt;
53
+ }
54
+
55
+ public function rotate_tt(){
56
+ $tt = $this->generate_tt();
57
+ is_network_admin() ? update_site_option( 'monsterinsights_network_tt', $tt ) : update_option( 'monsterinsights_site_tt', $tt );
58
+ }
59
+
60
+ public function generate_tt(){
61
+ return hash( 'sha512', wp_generate_password( 128, true, true ) . AUTH_SALT . uniqid( "", true ) );
62
+ }
63
+
64
+ public function validate_tt( $passed_tt = '' ) {
65
+ $tt = $this->get_tt();
66
+ return hash_equals( $tt, $passed_tt );
67
+ }
68
+
69
+ public function is_installed() {
70
+ wp_send_json_success(
71
+ array(
72
+ 'version' => MONSTERINSIGHTS_VERSION,
73
+ 'pro' => monsterinsights_is_pro_version(),
74
+ )
75
+ );
76
+ }
77
+
78
+ public function maybe_authenticate(){
79
+
80
+ // Check nonce
81
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
82
+
83
+ // current user can authenticate
84
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
85
+ wp_send_json_error( array( 'message' => __( "You don't have permission to authenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
86
+ }
87
+
88
+ if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
89
+ define( 'WP_NETWORK_ADMIN', true );
90
+ }
91
+
92
+ // Only for Pro users, require a license key to be entered first so we can link to things.
93
+ if ( monsterinsights_is_pro_version() ) {
94
+ $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
95
+ if ( ! $valid ) {
96
+ wp_send_json_error( array( 'message' => __( "Cannot authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
97
+ }
98
+ }
99
+
100
+ // we do not have a current auth
101
+ if ( ! $this->is_network_admin() && MonsterInsights()->auth->is_authed() ) {
102
+ wp_send_json_error( array( 'message' => __( "Cannot authenticate. Please re-authenticate.", 'google-analytics-for-wordpress' ) ) );
103
+ } else if ( $this->is_network_admin() && MonsterInsights()->auth->is_network_authed() ) {
104
+ wp_send_json_error( array( 'message' => __( "Cannot network authenticate. Please re-authenticate on the network settings panel.", 'google-analytics-for-wordpress' ) ) );
105
+ }
106
+
107
+ $sitei = $this->get_sitei();
108
+ //update_network_option( get_current_network_id(), 'monsterinsights_network_sitei', $sitei );
109
+
110
+ $siteurl = add_query_arg( array(
111
+ 'tt' => $this->get_tt(),
112
+ 'sitei' => $sitei,
113
+ 'miversion' => MONSTERINSIGHTS_VERSION,
114
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
115
+ 'network' => is_network_admin() ? 'network' : 'site',
116
+ 'siteurl' => is_network_admin() ? network_admin_url() : site_url(),
117
+ 'return' => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
118
+ 'testurl' => 'https://api.monsterinsights.com/v2/test/',
119
+ ), $this->get_route( 'https://' . monsterinsights_get_api_url() . 'auth/new/{type}' ) );
120
+
121
+ if ( monsterinsights_is_pro_version() ) {
122
+ $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
123
+ $siteurl = add_query_arg( 'license', $key, $siteurl );
124
+ }
125
+
126
+ $siteurl = apply_filters( 'monsterinsights_maybe_authenticate_siteurl', $siteurl );
127
+ wp_send_json_success( array( 'redirect' => $siteurl ) );
128
+ }
129
+
130
+ public function rauthenticate() {
131
+ // Check for missing params
132
+ $reqd_args = array( 'key', 'token', 'ua', 'miview', 'a', 'w', 'p', 'tt', 'network' );
133
+ foreach ( $reqd_args as $arg ) {
134
+ if ( empty( $_REQUEST[$arg] ) ) {
135
+ wp_send_json_error(
136
+ array(
137
+ 'error' => 'authenticate_missing_arg',
138
+ 'message' => 'Authenticate missing parameter: ' . $arg,
139
+ 'version' => MONSTERINSIGHTS_VERSION,
140
+ 'pro' => monsterinsights_is_pro_version(),
141
+ )
142
+ );
143
+ }
144
+ }
145
+
146
+ if ( ! empty( $_REQUEST['network'] ) && 'network' === $_REQUEST['network'] ) {
147
+ define( 'WP_NETWORK_ADMIN', true );
148
+ }
149
+
150
+ if ( ! $this->validate_tt( $_REQUEST['tt'] ) ) {
151
+ wp_send_json_error(
152
+ array(
153
+ 'error' => 'authenticate_invalid_tt',
154
+ 'message' => 'Invalid TT sent',
155
+ 'version' => MONSTERINSIGHTS_VERSION,
156
+ 'pro' => monsterinsights_is_pro_version(),
157
+ )
158
+ );
159
+ }
160
+
161
+ // If the tt is validated, send a success response to trigger the regular auth process.
162
+ wp_send_json_success();
163
+ }
164
+
165
+ public function authenticate_listener(){
166
+ // Make sure it's for us
167
+ if ( empty( $_REQUEST['mi-oauth-action'] ) || $_REQUEST['mi-oauth-action'] !== 'auth' ) {
168
+ return;
169
+ }
170
+
171
+ // User can authenticate
172
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
173
+ return;
174
+ }
175
+
176
+ // Invalid request
177
+ if ( empty( $_REQUEST['tt'] ) || ! $this->validate_tt( $_REQUEST['tt'] ) ) {
178
+ return;
179
+ }
180
+
181
+ // Make sure has required params
182
+ if ( empty( $_REQUEST['key'] ) ||
183
+ empty( $_REQUEST['token'] ) ||
184
+ empty( $_REQUEST['ua'] ) ||
185
+ empty( $_REQUEST['miview'] ) ||
186
+ empty( $_REQUEST['a'] ) ||
187
+ empty( $_REQUEST['w'] ) ||
188
+ empty( $_REQUEST['p'] )
189
+ ) {
190
+ return;
191
+ }
192
+
193
+ // Invalid UA code
194
+ $ua = monsterinsights_is_valid_ua( $_REQUEST['ua'] );
195
+ if ( empty( $ua ) ) {
196
+ return;
197
+ }
198
+
199
+ $profile = array(
200
+ 'key' => sanitize_text_field( $_REQUEST['key'] ),
201
+ 'token' => sanitize_text_field( $_REQUEST['token'] ),
202
+ 'ua' => monsterinsights_is_valid_ua( $_REQUEST['ua'] ),
203
+ 'viewname' => sanitize_text_field( $_REQUEST['miview'] ),
204
+ 'a' => sanitize_text_field( $_REQUEST['a'] ), // AccountID
205
+ 'w' => sanitize_text_field( $_REQUEST['w'] ), // PropertyID
206
+ 'p' => sanitize_text_field( $_REQUEST['p'] ), // View ID
207
+ 'siteurl' => site_url(),
208
+ 'neturl' => network_admin_url(),
209
+ );
210
+
211
+ $worked = $this->verify_auth( $profile );
212
+ if ( ! $worked || is_wp_error( $worked ) ) {
213
+ return;
214
+ }
215
+
216
+ // Save Profile
217
+ $this->is_network_admin() ? MonsterInsights()->auth->set_network_analytics_profile( $profile ) : MonsterInsights()->auth->set_analytics_profile( $profile );
218
+
219
+ // Clear cache
220
+ $where = $this->is_network_admin() ? 'network' : 'site';
221
+ MonsterInsights()->reporting->delete_aggregate_data( $where );
222
+
223
+ $url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ) ;
224
+ $url = add_query_arg( array(
225
+ 'mi_action' => 'auth',
226
+ 'success' => 'true',
227
+ ), $url );
228
+ $url = apply_filters( 'monsterinsights_auth_success_redirect_url', $url );
229
+ wp_safe_redirect( $url );
230
+ exit;
231
+ }
232
+
233
+ public function maybe_reauthenticate(){
234
+
235
+ // Check nonce
236
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
237
+
238
+ // current user can authenticate
239
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
240
+ wp_send_json_error( array( 'message' => __( "You don't have permission to re-authenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
241
+ }
242
+
243
+ if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
244
+ define( 'WP_NETWORK_ADMIN', true );
245
+ }
246
+
247
+ // Only for Pro users, require a license key to be entered first so we can link to things.
248
+ if ( monsterinsights_is_pro_version() ) {
249
+ $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
250
+ if ( monsterinsights_is_pro_version() && ! $valid ) {
251
+ wp_send_json_error( array( 'message' => __( "Cannot re-authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
252
+ }
253
+ }
254
+
255
+ // we do have a current auth
256
+ if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
257
+ wp_send_json_error( array( 'message' => __( "Cannot re-authenticate. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
258
+ } else if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
259
+ wp_send_json_error( array( 'message' => __( "Cannot re-authenticate the network. Please authenticate on the network settings panel.", 'google-analytics-for-wordpress' ) ) );
260
+ }
261
+
262
+ $siteurl = add_query_arg( array(
263
+ 'tt' => $this->get_tt(),
264
+ 'sitei' => $this->get_sitei(),
265
+ 'miversion' => MONSTERINSIGHTS_VERSION,
266
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
267
+ 'network' => is_network_admin() ? 'network' : 'site',
268
+ 'siteurl' => is_network_admin() ? network_admin_url() : site_url(),
269
+ 'key' => MonsterInsights()->auth->get_key(),
270
+ 'token' => MonsterInsights()->auth->get_token(),
271
+ 'return' => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
272
+ 'testurl' => 'https://api.monsterinsights.com/v2/test/',
273
+ ), $this->get_route( 'https://' . monsterinsights_get_api_url() . 'auth/reauth/{type}' ) );
274
+
275
+ if ( monsterinsights_is_pro_version() ) {
276
+ $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
277
+ $siteurl = add_query_arg( 'license', $key, $siteurl );
278
+ }
279
+
280
+ $siteurl = apply_filters( 'monsterinsights_maybe_authenticate_siteurl', $siteurl );
281
+
282
+ wp_send_json_success( array( 'redirect' => $siteurl ) );
283
+ }
284
+
285
+ public function reauthenticate_listener(){
286
+ // Make sure it's for us
287
+ if ( empty( $_REQUEST['mi-oauth-action'] ) || $_REQUEST['mi-oauth-action'] !== 'reauth' ) {
288
+ return;
289
+ }
290
+
291
+ // User can authenticate
292
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
293
+ return;
294
+ }
295
+
296
+ // Invalid request
297
+ if ( empty( $_REQUEST['tt'] ) || ! $this->validate_tt( $_REQUEST['tt'] ) ) {
298
+ return;
299
+ }
300
+
301
+ // Make sure has required params
302
+ if (
303
+ empty( $_REQUEST['ua'] ) ||
304
+ empty( $_REQUEST['miview'] ) ||
305
+ empty( $_REQUEST['a'] ) ||
306
+ empty( $_REQUEST['w'] ) ||
307
+ empty( $_REQUEST['p'] )
308
+ ) {
309
+ return;
310
+ }
311
+
312
+ // Invalid UA code
313
+ $ua = monsterinsights_is_valid_ua( $_REQUEST['ua'] );
314
+ if ( empty( $ua ) ) {
315
+ return;
316
+ }
317
+
318
+ // we do have a current auth
319
+ $existing = $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile() : MonsterInsights()->auth->get_analytics_profile();
320
+ if ( empty( $existing['key'] ) || empty( $existing['token'] ) ) {
321
+ return;
322
+ }
323
+
324
+ $profile = array(
325
+ 'key' => $existing['key'],
326
+ 'token' => $existing['token'],
327
+ 'ua' => monsterinsights_is_valid_ua( $_REQUEST['ua'] ),
328
+ 'viewname' => sanitize_text_field( $_REQUEST['miview'] ),
329
+ 'a' => sanitize_text_field( $_REQUEST['a'] ),
330
+ 'w' => sanitize_text_field( $_REQUEST['w'] ),
331
+ 'p' => sanitize_text_field( $_REQUEST['p'] ),
332
+ 'siteurl' => site_url(),
333
+ 'neturl' => network_admin_url(),
334
+ );
335
+
336
+ // Save Profile
337
+ $this->is_network_admin() ? MonsterInsights()->auth->set_network_analytics_profile( $profile ) : MonsterInsights()->auth->set_analytics_profile( $profile );
338
+
339
+ // Clear cache
340
+ $where = $this->is_network_admin() ? 'network' : 'site';
341
+ MonsterInsights()->reporting->delete_aggregate_data( $where );
342
+
343
+ $url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' ) ;
344
+ $url = add_query_arg( array(
345
+ 'mi_action' => 'reauth',
346
+ 'success' => 'true',
347
+ ), $url );
348
+ $url = apply_filters( 'monsterinsights_reauth_success_redirect_url', $url );
349
+
350
+ wp_safe_redirect( $url );
351
+ exit;
352
+ }
353
+
354
+ public function maybe_verify(){
355
+
356
+ // Check nonce
357
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
358
+
359
+ // current user can verify
360
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
361
+ wp_send_json_error( array( 'message' => __( "You don't have permission to verify MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
362
+ }
363
+
364
+ if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
365
+ define( 'WP_NETWORK_ADMIN', true );
366
+ }
367
+
368
+ // we have an auth to verify
369
+ if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
370
+ wp_send_json_error( array( 'message' => __( "Cannot verify. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
371
+ } else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
372
+ wp_send_json_error( array( 'message' => __( "Cannot verify. Please authenticate.", 'google-analytics-for-wordpress' ) ) );
373
+ }
374
+
375
+ if ( monsterinsights_is_pro_version() ) {
376
+ $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
377
+ if ( ! $valid ) {
378
+ wp_send_json_error( array( 'message' => __( "Cannot verify. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
379
+ }
380
+ }
381
+
382
+ $worked = $this->verify_auth();
383
+ if ( $worked && ! is_wp_error( $worked ) ) {
384
+ wp_send_json_success( array( 'message' => __( "Successfully verified.", 'google-analytics-for-wordpress' ) ) );
385
+ } else {
386
+ wp_send_json_error( array( 'message' => __( "Could not verify.", 'google-analytics-for-wordpress' ) ) );
387
+ }
388
+ }
389
+
390
+ public function verify_auth( $credentials = array() ){
391
+ $creds = ! empty( $credentials ) ? $credentials : ( $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile( true ) : MonsterInsights()->auth->get_analytics_profile( true ) );
392
+
393
+ if ( empty( $creds['key'] ) ) {
394
+ return new WP_Error( 'validation-error', sprintf( __( 'Verify auth key not passed', 'google-analytics-for-wordpress' ) ) );
395
+ }
396
+
397
+ $network = ! empty( $_REQUEST['network'] ) ? $_REQUEST['network'] === 'network' : $this->is_network_admin();
398
+ $api = new MonsterInsights_API_Request( $this->get_route( 'auth/verify/{type}/' ), array( 'network' => $network, 'tt' => $this->get_tt(), 'key' => $creds['key'], 'token' => $creds['token'], 'testurl' => 'https://api.monsterinsights.com/v2/test/' ) );
399
+ $ret = $api->request();
400
+
401
+ $this->rotate_tt();
402
+ if ( is_wp_error( $ret ) ) {
403
+ return $ret;
404
+ } else {
405
+ return true;
406
+ }
407
+ }
408
+
409
+ public function maybe_delete(){
410
+
411
+ // Check nonce
412
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
413
+
414
+ // current user can delete
415
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
416
+ wp_send_json_error( array( 'message' => __( "You don't have permission to deauthenticate MonsterInsights.", 'google-analytics-for-wordpress' ) ) );
417
+ }
418
+
419
+ if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
420
+ define( 'WP_NETWORK_ADMIN', true );
421
+ }
422
+
423
+ // we have an auth to delete
424
+ if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
425
+ wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. You are not currently authed.", 'google-analytics-for-wordpress' ) ) );
426
+ } else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
427
+ wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. You are not currently authed.", 'google-analytics-for-wordpress' ) ) );
428
+ }
429
+
430
+ if ( monsterinsights_is_pro_version() ) {
431
+ $valid = is_network_admin() ? MonsterInsights()->license->is_network_licensed() : MonsterInsights()->license->is_site_licensed();
432
+ if ( ! $valid ) {
433
+ wp_send_json_error( array( 'message' => __( "Cannot deauthenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings.", 'google-analytics-for-wordpress' ) ) );
434
+ }
435
+ }
436
+
437
+ $force = ! empty( $_REQUEST['forcedelete'] ) && $_REQUEST['forcedelete'] === 'true';
438
+
439
+ $worked = $this->delete_auth( $force );
440
+ if ( $worked && ! is_wp_error( $worked ) ) {
441
+ wp_send_json_success( array( 'message' => __( "Successfully deauthenticated.", 'google-analytics-for-wordpress' ) ) );
442
+ } else {
443
+ if ( $force ) {
444
+ wp_send_json_success( array( 'message' => __( "Successfully force deauthenticated.", 'google-analytics-for-wordpress' ) ) );
445
+ } else {
446
+ wp_send_json_error( array( 'message' => __( "Could not deauthenticate.", 'google-analytics-for-wordpress' ) ) );
447
+ }
448
+ }
449
+ }
450
+
451
+ public function delete_auth( $force = false ){
452
+ if ( $this->is_network_admin() && ! MonsterInsights()->auth->is_network_authed() ) {
453
+ return false;
454
+ } else if ( ! $this->is_network_admin() && ! MonsterInsights()->auth->is_authed() ) {
455
+ return false;
456
+ }
457
+
458
+ $creds = $this->is_network_admin() ? MonsterInsights()->auth->get_network_analytics_profile( true ) : MonsterInsights()->auth->get_analytics_profile( true );
459
+
460
+ if ( empty( $creds['key'] ) ) {
461
+ return false;
462
+ }
463
+
464
+ // If we have a new siteurl enabled option and the profile site doesn't match the current site, deactivate anyways
465
+ if ( is_network_admin() ) {
466
+ $siteurl = network_admin_url();
467
+ if ( ! empty( $creds['neturl' ] ) && $creds['neturl'] !== $siteurl ) {
468
+ MonsterInsights()->auth->delete_network_analytics_profile( true );
469
+ return true;
470
+ }
471
+ } else {
472
+ $siteurl = site_url();
473
+ if ( ! empty( $creds['siteurl' ] ) && $creds['siteurl'] !== $siteurl ) {
474
+ MonsterInsights()->auth->delete_analytics_profile( true );
475
+ return true;
476
+ }
477
+ }
478
+
479
+ $api = new MonsterInsights_API_Request( $this->get_route( 'auth/delete/{type}/' ), array( 'network' => $this->is_network_admin(), 'tt' => $this->get_tt(), 'key' => $creds['key'], 'token' => $creds['token'], 'testurl' => 'https://api.monsterinsights.com/v2/test/' ) );
480
+ $ret = $api->request();
481
+
482
+ $this->rotate_tt();
483
+ if ( is_wp_error( $ret ) && ! $force ) {
484
+ return false;
485
+ } else {
486
+ if ( $this->is_network_admin() ) {
487
+ MonsterInsights()->auth->delete_network_analytics_profile( true );
488
+ } else {
489
+ MonsterInsights()->auth->delete_analytics_profile( true );
490
+
491
+ }
492
+ return true;
493
+ }
494
+ }
495
+
496
+ /**
497
+ * Function to delete network auth in the uninstall process where we can't check if is network admin.
498
+ *
499
+ * @return bool
500
+ */
501
+ public function uninstall_network_auth() {
502
+
503
+ if ( ! MonsterInsights()->auth->is_network_authed() ) {
504
+ return false;
505
+ }
506
+
507
+ $creds = MonsterInsights()->auth->get_network_analytics_profile( true );
508
+
509
+ $api = new MonsterInsights_API_Request( $this->get_route( 'auth/delete/{type}/' ), array(
510
+ 'network' => true,
511
+ 'tt' => $this->get_tt(),
512
+ 'key' => $creds['key'],
513
+ 'token' => $creds['token'],
514
+ 'testurl' => 'https://api.monsterinsights.com/v2/test/'
515
+ ) );
516
+ // Force the network admin url otherwise this will fail not finding the url in relay.
517
+ $api->site_url = network_admin_url();
518
+ $ret = $api->request();
519
+
520
+ $this->rotate_tt();
521
+ if ( is_wp_error( $ret ) ) {
522
+ return false;
523
+ } else {
524
+ MonsterInsights()->auth->delete_network_analytics_profile( true );
525
+ return true;
526
+ }
527
+ }
528
+
529
+ public function get_type() {
530
+ $base = monsterinsights_is_pro_version() ? 'pro' : 'lite';
531
+ return apply_filters( 'monsterinsights_api_auth_get_type', $base );
532
+ }
533
+
534
+ public function get_route( $route = '' ) {
535
+ $route = str_replace( '{type}', $this->get_type(), $route );
536
+ $route = trailingslashit( $route );
537
+ return $route;
538
+ }
539
+
540
+ public function is_network_admin() {
541
+ return is_multisite() && is_network_admin();
542
+ }
543
+
544
+ public function get_sitei() {
545
+ // $sitei = get_network_option( get_current_network_id(), 'monsterinsights_network_sitei', false );
546
+ // if ( ! empty( $sitei ) && strlen( $sitei ) >= 1 ) {
547
+ // return $sitei;
548
+ // }
549
+
550
+ $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
551
+ $secure_auth_key = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
552
+ $logged_in_key = defined( 'LOGGED_IN_KEY' ) ? LOGGED_IN_KEY : '';
553
+
554
+ $sitei = $auth_key . $secure_auth_key . $logged_in_key;
555
+ $sitei = preg_replace('/[^a-zA-Z0-9]/', '', $sitei );
556
+ $sitei = sanitize_text_field( $sitei );
557
+ $sitei = trim( $sitei );
558
+ $sitei = ( strlen($sitei) > 30 ) ? substr($sitei, 0, 30 ) : $sitei;
559
+ return $sitei;
560
+ }
561
+
562
+ /**
563
+ * Logic to run before serving the redirect url during auth.
564
+ *
565
+ * @param string $url
566
+ *
567
+ * @return string
568
+ */
569
+ public function before_redirect( $url ) {
570
+
571
+ // If Bad Behavior plugin is installed.
572
+ if ( function_exists( 'bb2_read_settings' ) ) {
573
+ // Make sure the offsite_forms option is enabled to allow auth.
574
+ $bb_settings = get_option( 'bad_behavior_settings' );
575
+ if ( empty( $bb_settings['offsite_forms'] ) || false === $bb_settings['offsite_forms'] ) {
576
+ $bb_settings['offsite_forms'] = true;
577
+ update_option( 'bad_behavior_settings', $bb_settings );
578
+ }
579
+ }
580
+
581
+ return $url;
582
+ }
583
+ }
includes/admin/capabilities.php CHANGED
@@ -1,89 +1,89 @@
1
- <?php
2
- /**
3
- * Capabilities class.
4
- *
5
- * @access public
6
- * @since 6.0.0
7
- *
8
- * @package MonsterInsights
9
- * @subpackage Capabilities
10
- * @author Chris Christoff
11
- */
12
-
13
- // Exit if accessed directly
14
- if ( ! defined( 'ABSPATH' ) ) {
15
- exit;
16
- }
17
-
18
- /**
19
- * Map MonsterInsights Capabilities.
20
- *
21
- * Using meta caps, we're creating virtual capabilities that are
22
- * for backwards compatibility reasons given to users with manage_options, and to
23
- * users who have at least of the roles selected in the options on the permissions
24
- * tab of the MonsterInsights settings.
25
- *
26
- * @access public
27
- * @since 6.0.0
28
- *
29
- * @param array $caps Array of capabilities the user has.
30
- * @param string $cap The current cap being filtered.
31
- * @param int $user_id User to check permissions for.
32
- * @param array $args Extra parameters. Unused.
33
- * @return array Array of caps needed to have this meta cap. If returned array is empty, user has the capability.
34
- */
35
- function monsterinsights_add_capabilities( $caps, $cap, $user_id, $args ) {
36
-
37
- switch( $cap ) {
38
- case 'monsterinsights_view_dashboard' :
39
- $roles = monsterinsights_get_option( 'view_reports', array() );
40
-
41
- $user_can_via_settings = false;
42
- if ( ! empty( $roles ) && is_array( $roles ) ) {
43
- foreach ( $roles as $role ) {
44
- if ( is_string( $role ) ) {
45
- if ( user_can( $user_id, $role ) ) {
46
- $user_can_via_settings = true;
47
- break;
48
- }
49
- }
50
- }
51
- } else if ( ! empty( $roles ) && is_string( $roles ) ) {
52
- if ( user_can( $user_id, $roles ) ) {
53
- $user_can_via_settings = true;
54
- }
55
- }
56
-
57
- if ( user_can( $user_id, 'manage_options' ) || $user_can_via_settings ) {
58
- $caps = array();
59
- }
60
-
61
- break;
62
- case 'monsterinsights_save_settings' :
63
- $roles = monsterinsights_get_option( 'save_settings', array() );
64
-
65
- $user_can_via_settings = false;
66
- if ( ! empty( $roles ) && is_array( $roles ) ) {
67
- foreach ( $roles as $role ) {
68
- if ( is_string( $role ) ) {
69
- if ( user_can( $user_id, $role ) ) {
70
- $user_can_via_settings = true;
71
- break;
72
- }
73
- }
74
- }
75
- } else if ( ! empty( $roles ) && is_string( $roles ) ) {
76
- if ( user_can( $user_id, $roles ) ) {
77
- $user_can_via_settings = true;
78
- }
79
- }
80
-
81
- if ( user_can( $user_id, 'manage_options' ) || $user_can_via_settings ) {
82
- $caps = array();
83
- }
84
-
85
- break;
86
- }
87
- return $caps;
88
- }
89
  add_filter( 'map_meta_cap','monsterinsights_add_capabilities', 10, 4 );
1
+ <?php
2
+ /**
3
+ * Capabilities class.
4
+ *
5
+ * @access public
6
+ * @since 6.0.0
7
+ *
8
+ * @package MonsterInsights
9
+ * @subpackage Capabilities
10
+ * @author Chris Christoff
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit;
16
+ }
17
+
18
+ /**
19
+ * Map MonsterInsights Capabilities.
20
+ *
21
+ * Using meta caps, we're creating virtual capabilities that are
22
+ * for backwards compatibility reasons given to users with manage_options, and to
23
+ * users who have at least of the roles selected in the options on the permissions
24
+ * tab of the MonsterInsights settings.
25
+ *
26
+ * @access public
27
+ * @since 6.0.0
28
+ *
29
+ * @param array $caps Array of capabilities the user has.
30
+ * @param string $cap The current cap being filtered.
31
+ * @param int $user_id User to check permissions for.
32
+ * @param array $args Extra parameters. Unused.
33
+ * @return array Array of caps needed to have this meta cap. If returned array is empty, user has the capability.
34
+ */
35
+ function monsterinsights_add_capabilities( $caps, $cap, $user_id, $args ) {
36
+
37
+ switch( $cap ) {
38
+ case 'monsterinsights_view_dashboard' :
39
+ $roles = monsterinsights_get_option( 'view_reports', array() );
40
+
41
+ $user_can_via_settings = false;
42
+ if ( ! empty( $roles ) && is_array( $roles ) ) {
43
+ foreach ( $roles as $role ) {
44
+ if ( is_string( $role ) ) {
45
+ if ( user_can( $user_id, $role ) ) {
46
+ $user_can_via_settings = true;
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ } else if ( ! empty( $roles ) && is_string( $roles ) ) {
52
+ if ( user_can( $user_id, $roles ) ) {
53
+ $user_can_via_settings = true;
54
+ }
55
+ }
56
+
57
+ if ( user_can( $user_id, 'manage_options' ) || $user_can_via_settings ) {
58
+ $caps = array();
59
+ }
60
+
61
+ break;
62
+ case 'monsterinsights_save_settings' :
63
+ $roles = monsterinsights_get_option( 'save_settings', array() );
64
+
65
+ $user_can_via_settings = false;
66
+ if ( ! empty( $roles ) && is_array( $roles ) ) {
67
+ foreach ( $roles as $role ) {
68
+ if ( is_string( $role ) ) {
69
+ if ( user_can( $user_id, $role ) ) {
70
+ $user_can_via_settings = true;
71
+ break;
72
+ }
73
+ }
74
+ }
75
+ } else if ( ! empty( $roles ) && is_string( $roles ) ) {
76
+ if ( user_can( $user_id, $roles ) ) {
77
+ $user_can_via_settings = true;
78
+ }
79
+ }
80
+
81
+ if ( user_can( $user_id, 'manage_options' ) || $user_can_via_settings ) {
82
+ $caps = array();
83
+ }
84
+
85
+ break;
86
+ }
87
+ return $caps;
88
+ }
89
  add_filter( 'map_meta_cap','monsterinsights_add_capabilities', 10, 4 );
includes/admin/common.php CHANGED
@@ -1,811 +1,795 @@
1
- <?php
2
- /**
3
- * Common admin class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Common
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- function monsterinsights_is_settings_page() {
18
- $current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
19
- global $admin_page_hooks;
20
-
21
- if ( ! is_object( $current_screen ) || empty( $current_screen->id ) || empty( $admin_page_hooks ) ) {
22
- return false;
23
- }
24
-
25
- $settings_page = false;
26
- if ( ! empty( $admin_page_hooks['monsterinsights_settings'] ) && $current_screen->id === $admin_page_hooks['monsterinsights_settings'] ) {
27
- $settings_page = true;
28
- }
29
-
30
- if ( $current_screen->id === 'toplevel_page_monsterinsights_settings' ) {
31
- $settings_page = true;
32
- }
33
-
34
- if ( $current_screen->id === 'insights_page_monsterinsights_settings' ) {
35
- $settings_page = true;
36
- }
37
-
38
- if ( strpos( $current_screen->id, 'monsterinsights_settings' ) !== false ) {
39
- $settings_page = true;
40
- }
41
-
42
- if ( ! empty( $current_screen->base ) && strpos( $current_screen->base, 'monsterinsights_network' ) !== false ) {
43
- $settings_page = true;
44
- }
45
-
46
- return $settings_page;
47
- }
48
-
49
- /**
50
- * Determine if the current page is the Reports page.
51
- *
52
- * @return bool
53
- */
54
- function monsterinsights_is_reports_page() {
55
- $current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
56
- global $admin_page_hooks;
57
-
58
- if ( ! is_object( $current_screen ) || empty( $current_screen->id ) || empty( $admin_page_hooks ) ) {
59
- return false;
60
- }
61
-
62
- $settings_page = false;
63
- if ( ! empty( $admin_page_hooks['monsterinsights_reports'] ) && $current_screen->id === $admin_page_hooks['monsterinsights_reports'] ) {
64
- $settings_page = true;
65
- }
66
-
67
- if ( 'toplevel_page_monsterinsights_reports' === $current_screen->id ) {
68
- $settings_page = true;
69
- }
70
-
71
- if ( strpos( $current_screen->id, 'monsterinsights_reports' ) !== false ) {
72
- $settings_page = true;
73
- }
74
-
75
- if ( ! empty( $current_screen->base ) && strpos( $current_screen->base, 'monsterinsights_network' ) !== false ) {
76
- $settings_page = true;
77
- }
78
-
79
- return $settings_page;
80
- }
81
-
82
- /**
83
- * Loads styles for all MonsterInsights-based Administration Screens.
84
- *
85
- * @since 6.0.0
86
- * @access public
87
- *
88
- * @return null Return early if not on the proper screen.
89
- */
90
- function monsterinsights_admin_styles() {
91
-
92
- $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
93
-
94
- // Load Common admin styles.
95
- wp_register_style( 'monsterinsights-admin-common-style', plugins_url( 'assets/css/admin-common' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
96
- wp_enqueue_style( 'monsterinsights-admin-common-style' );
97
-
98
- // Get current screen.
99
- $screen = get_current_screen();
100
-
101
- // Bail if we're not on a MonsterInsights screen.
102
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
103
- return;
104
- }
105
-
106
- $version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
107
- $rtl = is_rtl() ? '.rtl' : '';
108
-
109
- // For the settings page, load the Vue app styles.
110
- if ( monsterinsights_is_settings_page() ) {
111
- if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
112
- wp_enqueue_style( 'monsterinsights-vue-style-vendors', plugins_url( $version_path . '/assets/vue/css/chunk-vendors' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
113
- wp_enqueue_style( 'monsterinsights-vue-style-common', plugins_url( $version_path . '/assets/vue/css/chunk-common' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
114
- wp_enqueue_style( 'monsterinsights-vue-style', plugins_url( $version_path . '/assets/vue/css/settings' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
115
- }
116
-
117
- // Don't load other styles on the settings page.
118
- return;
119
- }
120
-
121
- if ( monsterinsights_is_reports_page() ) {
122
- if ( ! defined( 'MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL' ) ) {
123
- wp_enqueue_style( 'monsterinsights-vue-style-vendors', plugins_url( $version_path . '/assets/vue/css/chunk-vendors' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
124
- wp_enqueue_style( 'monsterinsights-vue-style-common', plugins_url( $version_path . '/assets/vue/css/chunk-common' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
125
- wp_enqueue_style( 'monsterinsights-vue-style', plugins_url( $version_path . '/assets/vue/css/reports' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
126
- }
127
-
128
- return;
129
- }
130
-
131
-
132
- // Bootstrap
133
- // Primary
134
- wp_register_style( 'monsterinsights-bootstrap', plugins_url( 'assets/css/bootstrap-prefixed' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
135
- wp_enqueue_style( 'monsterinsights-bootstrap' );
136
-
137
- // Secondary
138
- //wp_register_style( 'monsterinsights-bootstrap-base', plugins_url( 'assets/css/bootstrap' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
139
- //wp_enqueue_style( 'monsterinsights-bootstrap-base' );
140
- //wp_register_style( 'monsterinsights-bootstrap-theme', plugins_url( 'assets/css/bootstrap-theme' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'monsterinsights-bootstrap-base' ), monsterinsights_get_asset_version() );
141
- //wp_enqueue_style( 'monsterinsights-bootstrap-theme' );
142
-
143
- // Vendors
144
- wp_register_style( 'monsterinsights-vendors-style', plugins_url( 'assets/css/vendors' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
145
- wp_enqueue_style( 'monsterinsights-vendors-style' );
146
-
147
- // Tooltips
148
- wp_enqueue_script( 'jquery-ui-tooltip' );
149
-
150
- // Load necessary admin styles.
151
- wp_register_style( 'monsterinsights-admin-style', plugins_url( 'assets/css/admin' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
152
- wp_enqueue_style( 'monsterinsights-admin-style' );
153
-
154
- // Load LTR stylesheet where needed.
155
- if ( is_rtl() ) {
156
- wp_enqueue_style( 'monsterinsights-admin-style-rtl', plugins_url( 'assets/css/admin-rtl' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
157
- }
158
- }
159
-
160
- add_action( 'admin_enqueue_scripts', 'monsterinsights_admin_styles' );
161
-
162
- /**
163
- * Loads scripts for all MonsterInsights-based Administration Screens.
164
- *
165
- * @since 6.0.0
166
- * @access public
167
- *
168
- * @return null Return early if not on the proper screen.
169
- */
170
- function monsterinsights_admin_scripts() {
171
-
172
- // Our Common Admin JS.
173
- $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
174
-
175
- wp_register_script( 'monsterinsights-admin-common-script', plugins_url( 'assets/js/admin-common' . $suffix . '.js', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'jquery' ), monsterinsights_get_asset_version() );
176
- wp_enqueue_script( 'monsterinsights-admin-common-script' );
177
- wp_localize_script(
178
- 'monsterinsights-admin-common-script',
179
- 'monsterinsights_admin_common',
180
- array(
181
- 'ajax' => admin_url( 'admin-ajax.php' ),
182
- 'dismiss_notice_nonce' => wp_create_nonce( 'monsterinsights-dismiss-notice' ),
183
- )
184
- );
185
-
186
- // Get current screen.
187
- $screen = get_current_screen();
188
-
189
- // Bail if we're not on a MonsterInsights screen.
190
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
191
- return;
192
- }
193
-
194
- $version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
195
-
196
- // For the settings page, load the Vue app.
197
- if ( monsterinsights_is_settings_page() ) {
198
- global $wp_version;
199
-
200
- if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
201
-
202
- wp_enqueue_script( 'monsterinsights-vue-vendors', plugins_url( $version_path . '/assets/vue/js/chunk-vendors.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
203
- wp_enqueue_script( 'monsterinsights-vue-common', plugins_url( $version_path . '/assets/vue/js/chunk-common.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
204
- }
205
- $app_js_url = defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) && MONSTERINSIGHTS_LOCAL_JS_URL ? MONSTERINSIGHTS_LOCAL_JS_URL : plugins_url( $version_path . '/assets/vue/js/settings.js', MONSTERINSIGHTS_PLUGIN_FILE );
206
- wp_register_script( 'monsterinsights-vue-script', $app_js_url, array(), monsterinsights_get_asset_version(), true );
207
- wp_enqueue_script( 'monsterinsights-vue-script' );
208
- $plugins = get_plugins();
209
- $install_amp_url = false;
210
- if ( current_user_can( 'install_plugins' ) ) {
211
- $amp_key = 'amp/amp.php';
212
- if ( array_key_exists( $amp_key, $plugins ) ) {
213
- $install_amp_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $amp_key ), 'activate-plugin_' . $amp_key );
214
- } else {
215
- $install_amp_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=amp' ), 'install-plugin_amp' );
216
- }
217
- }
218
- $install_fbia_url = false;
219
- if ( current_user_can( 'install_plugins' ) ) {
220
- $fbia_key = 'fb-instant-articles/facebook-instant-articles.php';
221
- if ( array_key_exists( $fbia_key, $plugins ) ) {
222
- $install_fbia_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $fbia_key ), 'activate-plugin_' . $fbia_key );
223
- } else {
224
- $install_fbia_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=fb-instant-articles' ), 'install-plugin_fb-instant-articles' );
225
- }
226
- }
227
-
228
- $prepared_dimensions = array();
229
- if ( class_exists( 'MonsterInsights_Admin_Custom_Dimensions' ) ) {
230
- $dimensions = new MonsterInsights_Admin_Custom_Dimensions();
231
- $dimensions = $dimensions->custom_dimensions();
232
- $prepared_dimensions = array();
233
- foreach ( $dimensions as $dimension_type => $dimension ) {
234
- $dimension['type'] = $dimension_type;
235
- $prepared_dimensions[] = $dimension;
236
- }
237
- }
238
-
239
- wp_localize_script(
240
- 'monsterinsights-vue-script',
241
- 'monsterinsights',
242
- array(
243
- 'ajax' => admin_url( 'admin-ajax.php' ),
244
- 'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
245
- 'network' => is_network_admin(),
246
- 'translations' => wp_get_jed_locale_data( monsterinsights_is_pro_version() ? 'ga-premium' : 'google-analytics-for-wordpress' ),
247
- 'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
248
- 'roles' => monsterinsights_get_roles(),
249
- 'roles_manage_options' => monsterinsights_get_manage_options_roles(),
250
- 'shareasale_id' => monsterinsights_get_shareasale_id(),
251
- 'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
252
- 'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
253
- 'install_amp_url' => $install_amp_url,
254
- 'install_fbia_url' => $install_fbia_url,
255
- 'dimensions' => $prepared_dimensions,
256
- 'wizard_url' => admin_url( 'index.php?page=monsterinsights-onboarding' ),
257
- 'install_plugins' => current_user_can( 'install_plugins' ),
258
- 'unfiltered_html' => current_user_can( 'unfiltered_html' ),
259
- 'activate_nonce' => wp_create_nonce( 'monsterinsights-activate' ),
260
- 'deactivate_nonce' => wp_create_nonce( 'monsterinsights-deactivate' ),
261
- 'install_nonce' => wp_create_nonce( 'monsterinsights-install' ),
262
- // Used to add notices for future deprecations.
263
- 'versions' => array(
264
- 'php_version' => phpversion(),
265
- 'php_version_below_54' => apply_filters( 'monsterinsights_temporarily_hide_php_52_and_53_upgrade_warnings', version_compare( phpversion(), '5.4', '<' ) ),
266
- 'php_version_below_56' => apply_filters( 'monsterinsights_temporarily_hide_php_54_and_55_upgrade_warnings', version_compare( phpversion(), '5.6', '<' ) ),
267
- 'php_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' ),
268
- 'wp_version' => $wp_version,
269
- 'wp_version_below_46' => version_compare( $wp_version, '4.6', '<' ),
270
- 'wp_version_below_49' => version_compare( $wp_version, '4.9', '<' ),
271
- 'wp_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' ),
272
- ),
273
- 'plugin_version' => MONSTERINSIGHTS_VERSION,
274
- 'is_admin' => true,
275
- 'reports_url' => add_query_arg( 'page', 'monsterinsights_reports', admin_url( 'admin.php' ) ),
276
- )
277
- );
278
-
279
- // Don't load other scripts on the settings page.
280
- return;
281
- }
282
-
283
- if ( monsterinsights_is_reports_page() ) {
284
- global $wp_version;
285
- if ( ! defined( 'MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL' ) ) {
286
- wp_enqueue_script( 'monsterinsights-vue-vendors', plugins_url( $version_path . '/assets/vue/js/chunk-vendors.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
287
- wp_enqueue_script( 'monsterinsights-vue-common', plugins_url( $version_path . '/assets/vue/js/chunk-common.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
288
- }
289
- $app_js_url = defined( 'MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL' ) && MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL ? MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL : plugins_url( $version_path . '/assets/vue/js/reports.js', MONSTERINSIGHTS_PLUGIN_FILE );
290
- wp_register_script( 'monsterinsights-vue-reports', $app_js_url, array(), monsterinsights_get_asset_version(), true );
291
- wp_enqueue_script( 'monsterinsights-vue-reports' );
292
-
293
- wp_localize_script(
294
- 'monsterinsights-vue-reports',
295
- 'monsterinsights',
296
- array(
297
- 'ajax' => admin_url( 'admin-ajax.php' ),
298
- 'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
299
- 'network' => is_network_admin(),
300
- 'translations' => wp_get_jed_locale_data( monsterinsights_is_pro_version() ? 'ga-premium' : 'google-analytics-for-wordpress' ),
301
- 'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
302
- 'shareasale_id' => monsterinsights_get_shareasale_id(),
303
- 'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
304
- 'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
305
- 'timezone' => date( 'e' ),
306
- // Used to add notices for future deprecations.
307
- 'versions' => array(
308
- 'php_version' => phpversion(),
309
- 'php_version_below_54' => apply_filters( 'monsterinsights_temporarily_hide_php_52_and_53_upgrade_warnings', version_compare( phpversion(), '5.4', '<' ) ),
310
- 'php_version_below_56' => apply_filters( 'monsterinsights_temporarily_hide_php_54_and_55_upgrade_warnings', version_compare( phpversion(), '5.6', '<' ) ),
311
- 'php_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' ),
312
- 'wp_version' => $wp_version,
313
- 'wp_version_below_46' => version_compare( $wp_version, '4.6', '<' ),
314
- 'wp_version_below_49' => version_compare( $wp_version, '4.9', '<' ),
315
- 'wp_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' ),
316
- ),
317
- 'plugin_version' => MONSTERINSIGHTS_VERSION,
318
- 'is_admin' => true,
319
- )
320
- );
321
- return;
322
- }
323
- // ublock notice
324
- add_action( 'admin_print_footer_scripts', 'monsterinsights_settings_ublock_error_js', 9999999 );
325
- }
326
-
327
- add_action( 'admin_enqueue_scripts', 'monsterinsights_admin_scripts' );
328
-
329
- /**
330
- * Remove Assets that conflict with ours from our screens.
331
- *
332
- * @since 6.0.4
333
- * @access public
334
- *
335
- * @return null Return early if not on the proper screen.
336
- */
337
- function monsterinsights_remove_conflicting_asset_files() {
338
-
339
- // Get current screen.
340
- $screen = get_current_screen();
341
-
342
- // Bail if we're not on a MonsterInsights screen.
343
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
344
- return;
345
- }
346
-
347
- $styles = array(
348
- 'kt_admin_css', // Pinnacle theme
349
- 'select2-css', // Schema theme
350
- 'tweetshare_style', // TweetShare - Click To Tweet
351
- 'tweetshare_custom_style', // TweetShare - Click To Tweet
352
- 'tweeetshare_custome_style', // TweetShare - Click To Tweet
353
- 'tweeetshare_notice_style', // TweetShare - Click To Tweet
354
- 'tweeetshare_theme_style', // TweetShare - Click To Tweet
355
- 'tweeetshare_tweet_box_style', // TweetShare - Click To Tweet
356
- 'soultype2-admin', // SoulType Plugin
357
- 'thesis-options-stylesheet', // Thesis Options Stylesheet
358
- 'imagify-sweetalert-core', // Imagify
359
- 'imagify-sweetalert', // Imagify
360
- 'smls-backend-style', // Smart Logo Showcase Lite
361
- 'wp-reactjs-starter', // wp-real-media-library
362
- 'control-panel-modal-plugin', // Ken Theme
363
- 'theme-admin-css', // Vitrine Theme
364
- 'qi-framework-styles', // Artisan Nayma Theme
365
- 'artisan-pages-style', // Artisan Pages Plugin
366
- 'control-panel-modal-plugin', // Ken Theme
367
- 'sweetalert', // Church Suite Theme by Webnus
368
- 'woo_stock_alerts_admin_css', // WooCommerce bolder product alerts
369
- 'custom_wp_admin_css', // Fix for Add Social Share
370
- 'fo_css', // Fix for Add Social Share
371
- 'font_css', // Fix for Add Social Share
372
- 'font2_css', // Fix for Add Social Share
373
- 'font3_css', // Fix for Add Social Share
374
- 'hover_css', // Fix for Add Social Share
375
- 'fontend_styling', // Fix for Add Social Share
376
- 'datatable', // WP Todo
377
- 'bootstrap', // WP Todo
378
- 'flipclock', // WP Todo
379
- 'repuso_css_admin', // Social testimonials and reviews by Repuso
380
- );
381
-
382
- $scripts = array(
383
- 'kad_admin_js', // Pinnacle theme
384
- 'dt-chart', // DesignThemes core features plugin
385
- 'tweeetshare_font_script', // TweetShare - Click To Tweet
386
- 'tweeetshare_jquery_script', // TweetShare - Click To Tweet
387
- 'tweeetshare_jqueryui_script', // TweetShare - Click To Tweet
388
- 'tweeetshare_custom_script', // TweetShare - Click To Tweet
389
- 'imagify-promise-polyfill', // Imagify
390
- 'imagify-sweetalert', // Imagify
391
- 'imagify-chart', // Imagify
392
- 'chartjs', // Comet Cache Pro
393
- 'wp-reactjs-starter', // wp-real-media-library
394
- 'jquery-tooltipster', // WP Real Media Library
395
- 'jquery-nested-sortable', // WP Real Media Library
396
- 'jquery-aio-tree', // WP Real Media Library
397
- 'wp-media-picker', // WP Real Media Library
398
- 'rml-general', // WP Real Media Library
399
- 'rml-library', // WP Real Media Library
400
- 'rml-grid', // WP Real Media Library
401
- 'rml-list', // WP Real Media Library
402
- 'rml-modal', // WP Real Media Library
403
- 'rml-order', // WP Real Media Library
404
- 'rml-meta', // WP Real Media Library
405
- 'rml-uploader', // WP Real Media Library
406
- 'rml-options', // WP Real Media Library
407
- 'rml-usersettings', // WP Real Media Library
408
- 'rml-main', // WP Real Media Library
409
- 'control-panel-sweet-alert', // Ken Theme
410
- 'sweet-alert-js', // Vitrine Theme
411
- 'theme-admin-script', // Vitrine Theme
412
- 'sweetalert', // Church Suite Theme by Webnus
413
- 'be_alerts_charts', // WooCommerce bolder product alerts
414
- 'magayo-lottery-results', // Magayo Lottery Results
415
- 'control-panel-sweet-alert', // Ken Theme
416
- 'cpm_chart', // WP Project Manager
417
- 'adminscripts', // Artisan Nayma Theme
418
- 'artisan-pages-script', // Artisan Pages Plugin
419
- 'tooltipster', // Grand News Theme
420
- 'fancybox', // Grand News Theme
421
- 'grandnews-admin-cript', // Grand News Theme
422
- 'colorpicker', // Grand News Theme
423
- 'eye', // Grand News Theme
424
- 'icheck', // Grand News Theme
425
- 'learn-press-chart', // LearnPress
426
- 'theme-script-main', // My Listing Theme by 27collective
427
- 'selz', // Selz eCommerce
428
- 'tie-admin-scripts', // Tie Theme
429
- 'blossomthemes-toolkit', // BlossomThemes Toolkit
430
- 'illdy-widget-upload-image', // Illdy Companion By Colorlib
431
- 'moment.js', // WooCommerce Table Rate Shipping
432
- 'default', // Bridge Theme
433
- 'qode-tax-js', // Bridge Theme
434
- 'wc_smartship_moment_js', // WooCommerce Posti SmartShip by markup.fi
435
- 'ecwid-admin-js', // Fixes Conflict for Ecwid Shopping Cart
436
- 'td-wp-admin-js', // Newspaper by tagDiv
437
- 'moment', // Screets Live Chat
438
- 'wpmf-base', // WP Media Folder Fix
439
- 'wpmf-media-filters', // WP Media Folder Fix
440
- 'wpmf-folder-tree', // WP Media Folder Fix
441
- 'wpmf-assign-tree', // WP Media Folder Fix
442
- 'js_files_for_wp_admin', // TagDiv Composer Fix
443
- 'tdb_js_files_for_wp_admin_last', // TagDiv Composer Fix
444
- 'tdb_js_files_for_wp_admin', // TagDiv Composer Fix
445
- 'wd-functions', // affiliate boxes
446
- 'ellk-aliExpansion', // Ali Dropship Plugin
447
- 'ftmetajs', // Houzez Theme
448
- 'qode_admin_default', // Fix For Stockholm Theme
449
- 'qodef-tax-js', // Fix for Prowess Theme
450
- 'qodef-user-js', // Fix for Prowess Theme
451
- 'qodef-ui-admin', // Fix for Prowess Theme
452
- 'ssi_script', // Fix for Add Social Share
453
- 'live_templates', // Fix for Add Social Share
454
- 'default', // Fix for Add Social Share
455
- 'handsontable', // Fix WP Tables
456
- 'moment-js', // Magee Shortcodes
457
- 'postbox', // Scripts from wp-admin enqueued everywhere by WP Posts Filter
458
- 'link', // Scripts from wp-admin enqueued everywhere by WP Posts Filter
459
- 'wpvr_scripts', // WP Video Robot
460
- 'wpvr_scripts_loaded', // WP Video Robot
461
- 'wpvr_scripts_assets', // WP Video Robot
462
- 'writee_widget_admin', // Fix for the Writtee theme
463
- '__ytprefs_admin__', // Fix for YouTube by EmbedPlus plugin
464
- 'momentjs', // Fix for Blog Time plugin
465
- 'c2c_BlogTime', // Fix for Blog Time plugin
466
- 'material-wp', // Fix for MaterialWP plugin
467
- 'wp-color-picker-alpha', // Fix for MaterialWP plugin
468
- 'grandtour-theme-script', // Grandtour Theme
469
- 'swifty-img-widget-admin-script', // Fix for Swifty Image Widget
470
- 'datatable', // WP Todo
471
- 'flipclock', // WP Todo
472
- 'bootstrap', // WP Todo
473
- 'repuso_js_admin', // Social testimonials and reviews by Repuso
474
- 'chart', // Video Mate Pro Theme
475
- 'reuse_vendor', // RedQ Reuse Form
476
- 'jetpack-onboarding-vendor', // Jetpack Onboarding Bluehost
477
- 'date-js', // Google Analytics by Web Dorado
478
- );
479
-
480
- if ( ! empty( $styles ) ) {
481
- foreach ( $styles as $style ) {
482
- wp_dequeue_style( $style ); // Remove CSS file from MI screen
483
- wp_deregister_style( $style );
484
- }
485
- }
486
- if ( ! empty( $scripts ) ) {
487
- foreach ( $scripts as $script ) {
488
- wp_dequeue_script( $script ); // Remove JS file from MI screen
489
- wp_deregister_script( $script );
490
- }
491
- }
492
-
493
- $third_party = array(
494
- 'select2',
495
- 'sweetalert',
496
- 'clipboard',
497
- 'matchHeight',
498
- 'inputmask',
499
- 'jquery-confirm',
500
- 'list',
501
- 'toastr',
502
- 'tooltipster',
503
- 'flag-icon',
504
- 'bootstrap',
505
- );
506
-
507
- global $wp_styles;
508
- foreach ( $wp_styles->queue as $handle ) {
509
- if ( strpos( $wp_styles->registered[ $handle ]->src, 'wp-content' ) === false ) {
510
- return;
511
- }
512
-
513
- if ( strpos( $wp_styles->registered[ $handle ]->handle, 'monsterinsights' ) !== false ) {
514
- return;
515
- }
516
-
517
- foreach ( $third_party as $partial ) {
518
- if ( strpos( $wp_styles->registered[ $handle ]->handle, $partial ) !== false ) {
519
- wp_dequeue_style( $handle ); // Remove css file from MI screen
520
- wp_deregister_style( $handle );
521
- break;
522
- } else if ( strpos( $wp_styles->registered[ $handle ]->src, $partial ) !== false ) {
523
- wp_dequeue_style( $handle ); // Remove css file from MI screen
524
- wp_deregister_style( $handle );
525
- break;
526
- }
527
- }
528
- }
529
-
530
- global $wp_scripts;
531
- foreach ( $wp_scripts->queue as $handle ) {
532
- if ( strpos( $wp_scripts->registered[ $handle ]->src, 'wp-content' ) === false ) {
533
- return;
534
- }
535
-
536
- if ( strpos( $wp_scripts->registered[ $handle ]->handle, 'monsterinsights' ) !== false ) {
537
- return;
538
- }
539
-
540
- foreach ( $third_party as $partial ) {
541
- if ( strpos( $wp_scripts->registered[ $handle ]->handle, $partial ) !== false ) {
542
- wp_dequeue_script( $handle ); // Remove JS file from MI screen
543
- wp_deregister_script( $handle );
544
- break;
545
- } else if ( strpos( $wp_scripts->registered[ $handle ]->src, $partial ) !== false ) {
546
- wp_dequeue_script( $handle ); // Remove JS file from MI screen
547
- wp_deregister_script( $handle );
548
- break;
549
- }
550
- }
551
- }
552
-
553
- // Remove actions from themes that are not following best practices and break the admin doing so
554
- // Theme: Newspaper by tagDiv
555
- remove_action( 'admin_enqueue_scripts', 'load_wp_admin_js' );
556
- remove_action( 'admin_enqueue_scripts', 'load_wp_admin_css' );
557
- remove_action( 'admin_print_scripts-widgets.php', 'td_on_admin_print_scripts_farbtastic' );
558
- remove_action( 'admin_print_styles-widgets.php', 'td_on_admin_print_styles_farbtastic' );
559
- remove_action( 'admin_print_footer_scripts', 'check_if_media_uploads_is_loaded', 9999 );
560
- remove_action( 'print_media_templates', 'td_custom_gallery_settings_hook' );
561
- remove_action( 'print_media_templates', 'td_change_backbone_js_hook' );
562
- remove_action( 'admin_head', 'tdc_on_admin_head' ); // TagDiv Composer Fix
563
- remove_action( 'print_media_templates', 'us_media_templates' ); // Impreza Theme Fix
564
- remove_action( 'admin_footer', 'gt3pg_add_gallery_template' ); // GT3 Photo & Video Gallery By GT3 Themes Plugin Fix
565
- // Plugin WP Booklist:
566
- remove_action( 'admin_footer', 'wpbooklist_jre_dismiss_prem_notice_forever_action_javascript' );
567
- remove_action( 'admin_footer', 'wpbooklist_dashboard_add_book_action_javascript' );
568
- remove_action( 'admin_footer', 'wpbooklist_edit_book_show_form_action_javascript' );
569
- remove_action( 'admin_footer', 'wpbooklist_show_book_in_colorbox_action_javascript' );
570
- remove_action( 'admin_footer', 'wpbooklist_new_lib_shortcode_action_javascript' );
571
- remove_action( 'admin_footer', 'wpbooklist_dashboard_save_library_display_options_action_javascript' );
572
- remove_action( 'admin_footer', 'wpbooklist_dashboard_save_post_display_options_action_javascript' );
573
- remove_action( 'admin_footer', 'wpbooklist_dashboard_save_page_display_options_action_javascript' );
574
- remove_action( 'admin_footer', 'wpbooklist_update_display_options_action_javascript' );
575
- remove_action( 'admin_footer', 'wpbooklist_edit_book_pagination_action_javascript' );
576
- remove_action( 'admin_footer', 'wpbooklist_edit_book_switch_lib_action_javascript' );
577
- remove_action( 'admin_footer', 'wpbooklist_edit_book_search_action_javascript' );
578
- remove_action( 'admin_footer', 'wpbooklist_edit_book_actual_action_javascript' );
579
- remove_action( 'admin_footer', 'wpbooklist_delete_book_action_javascript' );
580
- remove_action( 'admin_footer', 'wpbooklist_user_apis_action_javascript' );
581
- remove_action( 'admin_footer', 'wpbooklist_upload_new_stylepak_action_javascript' );
582
- remove_action( 'admin_footer', 'wpbooklist_upload_new_post_template_action_javascript' );
583
- remove_action( 'admin_footer', 'wpbooklist_upload_new_page_template_action_javascript' );
584
- remove_action( 'admin_footer', 'wpbooklist_create_db_library_backup_action_javascript' );
585
- remove_action( 'admin_footer', 'wpbooklist_restore_db_library_backup_action_javascript' );
586
- remove_action( 'admin_footer', 'wpbooklist_create_csv_action_javascript' );
587
- remove_action( 'admin_footer', 'wpbooklist_amazon_localization_action_javascript' );
588
- remove_action( 'admin_footer', 'wpbooklist_delete_book_bulk_action_javascript' );
589
- remove_action( 'admin_footer', 'wpbooklist_reorder_action_javascript' );
590
- remove_action( 'admin_footer', 'wpbooklist_exit_results_action_javascript' );
591
- remove_action( 'admin_footer', 'wpbooklist_storytime_select_category_action_javascript' );
592
- remove_action( 'admin_footer', 'wpbooklist_storytime_get_story_action_javascript' );
593
- remove_action( 'admin_footer', 'wpbooklist_storytime_expand_browse_action_javascript' );
594
- remove_action( 'admin_footer', 'wpbooklist_storytime_save_settings_action_javascript' );
595
- remove_action( 'admin_footer', 'wpbooklist_delete_story_action_javascript' );
596
- }
597
-
598
- add_action( 'admin_enqueue_scripts', 'monsterinsights_remove_conflicting_asset_files', 9999 );
599
-
600
- /**
601
- * Remove non-MI notices from MI page.
602
- *
603
- * @since 6.0.0
604
- * @access public
605
- *
606
- * @return null Return early if not on the proper screen.
607
- */
608
- function hide_non_monsterinsights_warnings() {
609
- // Bail if we're not on a MonsterInsights screen.
610
- if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], 'monsterinsights' ) === false ) {
611
- return;
612
- }
613
-
614
- global $wp_filter;
615
- if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
616
- foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
617
- foreach ( $hooks as $name => $arr ) {
618
- if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
619
- unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
620
- continue;
621
- }
622
- if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'monsterinsights' ) !== false ) {
623
- continue;
624
- }
625
- if ( ! empty( $name ) && strpos( $name, 'monsterinsights' ) === false ) {
626
- unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
627
- }
628
- }
629
- }
630
- }
631
-
632
- if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
633
- foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
634
- foreach ( $hooks as $name => $arr ) {
635
- if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
636
- unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
637
- continue;
638
- }
639
- if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'monsterinsights' ) !== false ) {
640
- continue;
641
- }
642
- if ( ! empty( $name ) && strpos( $name, 'monsterinsights' ) === false ) {
643
- unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
644
- }
645
- }
646
- }
647
- }
648
-
649
- if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
650
- foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
651
- foreach ( $hooks as $name => $arr ) {
652
- if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
653
- unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
654
- continue;
655
- }
656
- if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'monsterinsights' ) !== false ) {
657
- continue;
658
- }
659
- if ( ! empty( $name ) && strpos( $name, 'monsterinsights' ) === false ) {
660
- unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
661
- }
662
- }
663
- }
664
- }
665
- }
666
-
667
- add_action( 'admin_print_scripts', 'hide_non_monsterinsights_warnings' );
668
- add_action( 'admin_head', 'hide_non_monsterinsights_warnings', PHP_INT_MAX );
669
-
670
- /**
671
- * Called whenever an upgrade button / link is displayed in Lite, this function will
672
- * check if there's a shareasale ID specified.
673
- *
674
- * There are three ways to specify an ID, ordered by highest to lowest priority
675
- * - add_filter( 'monsterinsights_shareasale_id', function() { return 1234; } );
676
- * - define( 'MONSTERINSIGHTS_SHAREASALE_ID', 1234 );
677
- * - get_option( 'monsterinsights_shareasale_id' ); (with the option being in the wp_options table)
678
- *
679
- * If an ID is present, returns the ShareASale link with the affiliate ID, and tells
680
- * ShareASale to then redirect to monsterinsights.com/lite
681
- *
682
- * If no ID is present, just returns the monsterinsights.com/lite URL with UTM tracking.
683
- *
684
- * @since 6.0.0
685
- * @access public
686
- *
687
- * @return string Upgrade link.
688
- */
689
- function monsterinsights_get_upgrade_link( $medium = '', $campaign = '', $url = '' ) {
690
- $url = monsterinsights_get_url( $medium, $campaign, $url, false );
691
-
692
- if ( monsterinsights_is_pro_version() ) {
693
- return esc_url( $url );
694
- }
695
-
696
- // Get the ShareASale ID
697
- $shareasale_id = monsterinsights_get_shareasale_id();
698
-
699
- // If we have a shareasale ID return the shareasale url
700
- if ( ! empty( $shareasale_id ) ) {
701
- $shareasale_id = absint( $shareasale_id );
702
-
703
- return esc_url( monsterinsights_get_shareasale_url( $shareasale_id, $url ) );
704
- } else {
705
- return esc_url( $url );
706
- }
707
- }
708
-
709
- function monsterinsights_get_url( $medium = '', $campaign = '', $url = '', $escape = true ) {
710
- // Setup Campaign variables
711
- $source = monsterinsights_is_pro_version() ? 'proplugin' : 'liteplugin';
712
- $medium = ! empty( $medium ) ? $medium : 'defaultmedium';
713
- $campaign = ! empty( $campaign ) ? $campaign : 'defaultcampaign';
714
- $content = MONSTERINSIGHTS_VERSION;
715
- $default_url = monsterinsights_is_pro_version() ? '' : 'lite/';
716
- $url = ! empty( $url ) ? $url : 'https://www.monsterinsights.com/' . $default_url;
717
-
718
- // Put together redirect URL
719
- $url = add_query_arg(
720
- array(
721
- 'utm_source' => $source, // Pro/Lite Plugin
722
- 'utm_medium' => sanitize_key( $medium ), // Area of MonsterInsights (example Reports)
723
- 'utm_campaign' => sanitize_key( $campaign ), // Which link (example eCommerce Report)
724
- 'utm_content' => $content, // Version number of MI
725
- ),
726
- trailingslashit( $url )
727
- );
728
-
729
- if ( $escape ) {
730
- return esc_url( $url );
731
- } else {
732
- return $url;
733
- }
734
- }
735
-
736
- function monsterinsights_settings_ublock_error_js() {
737
- echo "<script type='text/javascript'>\n";
738
- echo "jQuery( document ).ready( function( $ ) {
739
- if ( window.uorigindetected == null){
740
- $('#monsterinsights-ublock-origin-error').show();
741
- $('.monsterinsights-nav-tabs').hide();
742
- $('.monsterinsights-nav-container').hide();
743
- $('#monsterinsights-addon-heading').hide();
744
- $('#monsterinsights-addons').hide();
745
- $('#monsterinsights-reports').hide();
746
- }
747
- });";
748
- echo "\n</script>";
749
- }
750
-
751
- function monsterinsights_ublock_notice() {
752
- ob_start(); ?>
753
- <div id="monsterinsights-ublock-origin-error" class="error inline" style="display:none;">
754
- <?php echo sprintf( esc_html__( 'MonsterInsights has detected that it\'s files are being blocked. This is usually caused by a adblock browser plugin (particularly uBlock Origin), or a conflicting WordPress theme or plugin. This issue only affects the admin side of MonsterInsights. To solve this, ensure MonsterInsights is whitelisted for your website URL in any adblock browser plugin you use. For step by step directions on how to do this, %1$sclick here%2$s. If this doesn\'t solve the issue (rare), send us a ticket %3$shere%2$s and we\'ll be happy to help diagnose the issue.', 'google-analytics-for-wordpress' ), '<a href="https://monsterinsights.com/docs/monsterinsights-asset-files-blocked/" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>', '<a href="https://monsterinsights.com/contact/" target="_blank" rel="noopener noreferrer" referrer="no-referrer">' );
755
- ?>
756
- </div>
757
- <?php
758
- return ob_get_clean();
759
- }
760
-
761
- /**
762
- * Some themes/plugins don't add proper checks and load JS code in all admin pages causing conflicts.
763
- */
764
- function monsterinsights_remove_unnecessary_footer_hooks() {
765
-
766
- $screen = get_current_screen();
767
- // Bail if we're not on a MonsterInsights screen.
768
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
769
- return;
770
- }
771
-
772
- // Remove js code added by Newspaper theme - version 8.8.0.
773
- remove_action( 'print_media_templates', 'td_custom_gallery_settings_hook' );
774
- remove_action( 'print_media_templates', 'td_change_backbone_js_hook' );
775
- // Remove js code added by the Brooklyn theme - version 4.5.3.1.
776
- remove_action( 'print_media_templates', 'ut_create_gallery_options' );
777
-
778
- // Remove js code added by WordPress Book List Plugin - version 5.8.1.
779
- remove_action( 'admin_footer', 'wpbooklist_jre_dismiss_prem_notice_forever_action_javascript' );
780
- remove_action( 'admin_footer', 'wpbooklist_dashboard_add_book_action_javascript' );
781
- remove_action( 'admin_footer', 'wpbooklist_edit_book_show_form_action_javascript' );
782
- remove_action( 'admin_footer', 'wpbooklist_show_book_in_colorbox_action_javascript' );
783
- remove_action( 'admin_footer', 'wpbooklist_new_lib_shortcode_action_javascript' );
784
- remove_action( 'admin_footer', 'wpbooklist_dashboard_save_library_display_options_action_javascript' );
785
- remove_action( 'admin_footer', 'wpbooklist_dashboard_save_post_display_options_action_javascript' );
786
- remove_action( 'admin_footer', 'wpbooklist_dashboard_save_page_display_options_action_javascript' );
787
- remove_action( 'admin_footer', 'wpbooklist_update_display_options_action_javascript' );
788
- remove_action( 'admin_footer', 'wpbooklist_edit_book_pagination_action_javascript' );
789
- remove_action( 'admin_footer', 'wpbooklist_edit_book_switch_lib_action_javascript' );
790
- remove_action( 'admin_footer', 'wpbooklist_edit_book_search_action_javascript' );
791
- remove_action( 'admin_footer', 'wpbooklist_edit_book_actual_action_javascript' );
792
- remove_action( 'admin_footer', 'wpbooklist_delete_book_action_javascript' );
793
- remove_action( 'admin_footer', 'wpbooklist_user_apis_action_javascript' );
794
- remove_action( 'admin_footer', 'wpbooklist_upload_new_stylepak_action_javascript' );
795
- remove_action( 'admin_footer', 'wpbooklist_upload_new_post_template_action_javascript' );
796
- remove_action( 'admin_footer', 'wpbooklist_upload_new_page_template_action_javascript' );
797
- remove_action( 'admin_footer', 'wpbooklist_create_db_library_backup_action_javascript' );
798
- remove_action( 'admin_footer', 'wpbooklist_restore_db_library_backup_action_javascript' );
799
- remove_action( 'admin_footer', 'wpbooklist_create_csv_action_javascript' );
800
- remove_action( 'admin_footer', 'wpbooklist_amazon_localization_action_javascript' );
801
- remove_action( 'admin_footer', 'wpbooklist_delete_book_bulk_action_javascript' );
802
- remove_action( 'admin_footer', 'wpbooklist_reorder_action_javascript' );
803
- remove_action( 'admin_footer', 'wpbooklist_exit_results_action_javascript' );
804
- remove_action( 'admin_footer', 'wpbooklist_storytime_select_category_action_javascript' );
805
- remove_action( 'admin_footer', 'wpbooklist_storytime_get_story_action_javascript' );
806
- remove_action( 'admin_footer', 'wpbooklist_storytime_expand_browse_action_javascript' );
807
- remove_action( 'admin_footer', 'wpbooklist_storytime_save_settings_action_javascript' );
808
- remove_action( 'admin_footer', 'wpbooklist_delete_story_action_javascript' );
809
- }
810
-
811
- add_action( 'admin_head', 'monsterinsights_remove_unnecessary_footer_hooks', 15 );
1
+ <?php
2
+ /**
3
+ * Common admin class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Common
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ function monsterinsights_is_settings_page() {
18
+ $current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
19
+ global $admin_page_hooks;
20
+
21
+ if ( ! is_object( $current_screen ) || empty( $current_screen->id ) || empty( $admin_page_hooks ) ) {
22
+ return false;
23
+ }
24
+
25
+ $settings_page = false;
26
+ if ( ! empty( $admin_page_hooks['monsterinsights_settings'] ) && $current_screen->id === $admin_page_hooks['monsterinsights_settings'] ) {
27
+ $settings_page = true;
28
+ }
29
+
30
+ if ( $current_screen->id === 'toplevel_page_monsterinsights_settings' ) {
31
+ $settings_page = true;
32
+ }
33
+
34
+ if ( $current_screen->id === 'insights_page_monsterinsights_settings' ) {
35
+ $settings_page = true;
36
+ }
37
+
38
+ if ( strpos( $current_screen->id, 'monsterinsights_settings' ) !== false ) {
39
+ $settings_page = true;
40
+ }
41
+
42
+ if ( ! empty( $current_screen->base ) && strpos( $current_screen->base, 'monsterinsights_network' ) !== false ) {
43
+ $settings_page = true;
44
+ }
45
+
46
+ return $settings_page;
47
+ }
48
+
49
+ /**
50
+ * Determine if the current page is the Reports page.
51
+ *
52
+ * @return bool
53
+ */
54
+ function monsterinsights_is_reports_page() {
55
+ $current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
56
+ global $admin_page_hooks;
57
+
58
+ if ( ! is_object( $current_screen ) || empty( $current_screen->id ) || empty( $admin_page_hooks ) ) {
59
+ return false;
60
+ }
61
+
62
+ $settings_page = false;
63
+ if ( ! empty( $admin_page_hooks['monsterinsights_reports'] ) && $current_screen->id === $admin_page_hooks['monsterinsights_reports'] ) {
64
+ $settings_page = true;
65
+ }
66
+
67
+ if ( 'toplevel_page_monsterinsights_reports' === $current_screen->id ) {
68
+ $settings_page = true;
69
+ }
70
+
71
+ if ( strpos( $current_screen->id, 'monsterinsights_reports' ) !== false ) {
72
+ $settings_page = true;
73
+ }
74
+
75
+ if ( ! empty( $current_screen->base ) && strpos( $current_screen->base, 'monsterinsights_network' ) !== false ) {
76
+ $settings_page = true;
77
+ }
78
+
79
+ return $settings_page;
80
+ }
81
+
82
+ /**
83
+ * Loads styles for all MonsterInsights-based Administration Screens.
84
+ *
85
+ * @return null Return early if not on the proper screen.
86
+ * @since 6.0.0
87
+ * @access public
88
+ *
89
+ */
90
+ function monsterinsights_admin_styles() {
91
+
92
+ $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
93
+
94
+ // Load Common admin styles.
95
+ wp_register_style( 'monsterinsights-admin-common-style', plugins_url( 'assets/css/admin-common' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
96
+ wp_enqueue_style( 'monsterinsights-admin-common-style' );
97
+
98
+ // Get current screen.
99
+ $screen = get_current_screen();
100
+
101
+ // Bail if we're not on a MonsterInsights screen.
102
+ if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
103
+ return;
104
+ }
105
+
106
+ $version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
107
+ $rtl = is_rtl() ? '.rtl' : '';
108
+
109
+ // For the settings page, load the Vue app styles.
110
+ if ( monsterinsights_is_settings_page() ) {
111
+ if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
112
+ wp_enqueue_style( 'monsterinsights-vue-style-vendors', plugins_url( $version_path . '/assets/vue/css/chunk-vendors' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
113
+ wp_enqueue_style( 'monsterinsights-vue-style-common', plugins_url( $version_path . '/assets/vue/css/chunk-common' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
114
+ wp_enqueue_style( 'monsterinsights-vue-style', plugins_url( $version_path . '/assets/vue/css/settings' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
115
+ }
116
+
117
+ // Don't load other styles on the settings page.
118
+ return;
119
+ }
120
+
121
+ if ( monsterinsights_is_reports_page() ) {
122
+ if ( ! defined( 'MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL' ) ) {
123
+ wp_enqueue_style( 'monsterinsights-vue-style-vendors', plugins_url( $version_path . '/assets/vue/css/chunk-vendors' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
124
+ wp_enqueue_style( 'monsterinsights-vue-style-common', plugins_url( $version_path . '/assets/vue/css/chunk-common' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
125
+ wp_enqueue_style( 'monsterinsights-vue-style', plugins_url( $version_path . '/assets/vue/css/reports' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
126
+ }
127
+
128
+ return;
129
+ }
130
+
131
+ // Tooltips
132
+ wp_enqueue_script( 'jquery-ui-tooltip' );
133
+ }
134
+
135
+ add_action( 'admin_enqueue_scripts', 'monsterinsights_admin_styles' );
136
+
137
+ /**
138
+ * Loads scripts for all MonsterInsights-based Administration Screens.
139
+ *
140
+ * @return null Return early if not on the proper screen.
141
+ * @since 6.0.0
142
+ * @access public
143
+ *
144
+ */
145
+ function monsterinsights_admin_scripts() {
146
+
147
+ // Our Common Admin JS.
148
+ $suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
149
+
150
+ wp_register_script( 'monsterinsights-admin-common-script', plugins_url( 'assets/js/admin-common' . $suffix . '.js', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'jquery' ), monsterinsights_get_asset_version() );
151
+ wp_enqueue_script( 'monsterinsights-admin-common-script' );
152
+ wp_localize_script(
153
+ 'monsterinsights-admin-common-script',
154
+ 'monsterinsights_admin_common',
155
+ array(
156
+ 'ajax' => admin_url( 'admin-ajax.php' ),
157
+ 'dismiss_notice_nonce' => wp_create_nonce( 'monsterinsights-dismiss-notice' ),
158
+ )
159
+ );
160
+
161
+ // Get current screen.
162
+ $screen = get_current_screen();
163
+
164
+ // Bail if we're not on a MonsterInsights screen.
165
+ if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
166
+ return;
167
+ }
168
+
169
+ $version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
170
+
171
+ // For the settings page, load the Vue app.
172
+ if ( monsterinsights_is_settings_page() ) {
173
+ global $wp_version;
174
+
175
+ if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
176
+
177
+ wp_enqueue_script( 'monsterinsights-vue-vendors', plugins_url( $version_path . '/assets/vue/js/chunk-vendors.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
178
+ wp_enqueue_script( 'monsterinsights-vue-common', plugins_url( $version_path . '/assets/vue/js/chunk-common.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
179
+ }
180
+ $app_js_url = defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) && MONSTERINSIGHTS_LOCAL_JS_URL ? MONSTERINSIGHTS_LOCAL_JS_URL : plugins_url( $version_path . '/assets/vue/js/settings.js', MONSTERINSIGHTS_PLUGIN_FILE );
181
+ wp_register_script( 'monsterinsights-vue-script', $app_js_url, array(), monsterinsights_get_asset_version(), true );
182
+ wp_enqueue_script( 'monsterinsights-vue-script' );
183
+ $plugins = get_plugins();
184
+ $install_amp_url = false;
185
+ if ( current_user_can( 'install_plugins' ) ) {
186
+ $amp_key = 'amp/amp.php';
187
+ if ( array_key_exists( $amp_key, $plugins ) ) {
188
+ $install_amp_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $amp_key ), 'activate-plugin_' . $amp_key );
189
+ } else {
190
+ $install_amp_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=amp' ), 'install-plugin_amp' );
191
+ }
192
+ }
193
+ $install_fbia_url = false;
194
+ if ( current_user_can( 'install_plugins' ) ) {
195
+ $fbia_key = 'fb-instant-articles/facebook-instant-articles.php';
196
+ if ( array_key_exists( $fbia_key, $plugins ) ) {
197
+ $install_fbia_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $fbia_key ), 'activate-plugin_' . $fbia_key );
198
+ } else {
199
+ $install_fbia_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=fb-instant-articles' ), 'install-plugin_fb-instant-articles' );
200
+ }
201
+ }
202
+
203
+ $prepared_dimensions = array();
204
+ if ( class_exists( 'MonsterInsights_Admin_Custom_Dimensions' ) ) {
205
+ $dimensions = new MonsterInsights_Admin_Custom_Dimensions();
206
+ $dimensions = $dimensions->custom_dimensions();
207
+ $prepared_dimensions = array();
208
+ foreach ( $dimensions as $dimension_type => $dimension ) {
209
+ $dimension['type'] = $dimension_type;
210
+ $prepared_dimensions[] = $dimension;
211
+ }
212
+ }
213
+
214
+ wp_localize_script(
215
+ 'monsterinsights-vue-script',
216
+ 'monsterinsights',
217
+ array(
218
+ 'ajax' => admin_url( 'admin-ajax.php' ),
219
+ 'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
220
+ 'network' => is_network_admin(),
221
+ 'translations' => wp_get_jed_locale_data( monsterinsights_is_pro_version() ? 'ga-premium' : 'google-analytics-for-wordpress' ),
222
+ 'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
223
+ 'roles' => monsterinsights_get_roles(),
224
+ 'roles_manage_options' => monsterinsights_get_manage_options_roles(),
225
+ 'shareasale_id' => monsterinsights_get_shareasale_id(),
226
+ 'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
227
+ 'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
228
+ 'install_amp_url' => $install_amp_url,
229
+ 'install_fbia_url' => $install_fbia_url,
230
+ 'dimensions' => $prepared_dimensions,
231
+ 'wizard_url' => admin_url( 'index.php?page=monsterinsights-onboarding' ),
232
+ 'install_plugins' => current_user_can( 'install_plugins' ),
233
+ 'unfiltered_html' => current_user_can( 'unfiltered_html' ),
234
+ 'activate_nonce' => wp_create_nonce( 'monsterinsights-activate' ),
235
+ 'deactivate_nonce' => wp_create_nonce( 'monsterinsights-deactivate' ),
236
+ 'install_nonce' => wp_create_nonce( 'monsterinsights-install' ),
237
+ // Used to add notices for future deprecations.
238
+ 'versions' => array(
239
+ 'php_version' => phpversion(),
240
+ 'php_version_below_54' => apply_filters( 'monsterinsights_temporarily_hide_php_52_and_53_upgrade_warnings', version_compare( phpversion(), '5.4', '<' ) ),
241
+ 'php_version_below_56' => apply_filters( 'monsterinsights_temporarily_hide_php_54_and_55_upgrade_warnings', version_compare( phpversion(), '5.6', '<' ) ),
242
+ 'php_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' ),
243
+ 'wp_version' => $wp_version,
244
+ 'wp_version_below_46' => version_compare( $wp_version, '4.6', '<' ),
245
+ 'wp_version_below_49' => version_compare( $wp_version, '4.9', '<' ),
246
+ 'wp_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' ),
247
+ ),
248
+ 'plugin_version' => MONSTERINSIGHTS_VERSION,
249
+ 'is_admin' => true,
250
+ 'reports_url' => add_query_arg( 'page', 'monsterinsights_reports', admin_url( 'admin.php' ) ),
251
+ 'first_run_notice' => apply_filters( 'monsterinsights_settings_first_time_notice_hide', monsterinsights_get_option( 'monsterinsights_first_run_notice' ) ),
252
+ )
253
+ );
254
+
255
+ // Don't load other scripts on the settings page.
256
+ return;
257
+ }
258
+
259
+ if ( monsterinsights_is_reports_page() ) {
260
+ global $wp_version;
261
+ if ( ! defined( 'MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL' ) ) {
262
+ wp_enqueue_script( 'monsterinsights-vue-vendors', plugins_url( $version_path . '/assets/vue/js/chunk-vendors.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
263
+ wp_enqueue_script( 'monsterinsights-vue-common', plugins_url( $version_path . '/assets/vue/js/chunk-common.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
264
+ }
265
+ $app_js_url = defined( 'MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL' ) && MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL ? MONSTERINSIGHTS_LOCAL_REPORTS_JS_URL : plugins_url( $version_path . '/assets/vue/js/reports.js', MONSTERINSIGHTS_PLUGIN_FILE );
266
+ wp_register_script( 'monsterinsights-vue-reports', $app_js_url, array(), monsterinsights_get_asset_version(), true );
267
+ wp_enqueue_script( 'monsterinsights-vue-reports' );
268
+
269
+ // We do not have a current auth.
270
+ $site_auth = MonsterInsights()->auth->get_viewname();
271
+ $ms_auth = is_multisite() && MonsterInsights()->auth->get_network_viewname();
272
+
273
+ wp_localize_script(
274
+ 'monsterinsights-vue-reports',
275
+ 'monsterinsights',
276
+ array(
277
+ 'ajax' => admin_url( 'admin-ajax.php' ),
278
+ 'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
279
+ 'network' => is_network_admin(),
280
+ 'translations' => wp_get_jed_locale_data( monsterinsights_is_pro_version() ? 'ga-premium' : 'google-analytics-for-wordpress' ),
281
+ 'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
282
+ 'shareasale_id' => monsterinsights_get_shareasale_id(),
283
+ 'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
284
+ 'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
285
+ 'timezone' => date( 'e' ),
286
+ 'authed' => $site_auth || $ms_auth,
287
+ 'settings_url' => add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) ),
288
+ // Used to add notices for future deprecations.
289
+ 'versions' => array(
290
+ 'php_version' => phpversion(),
291
+ 'php_version_below_54' => apply_filters( 'monsterinsights_temporarily_hide_php_52_and_53_upgrade_warnings', version_compare( phpversion(), '5.4', '<' ) ),
292
+ 'php_version_below_56' => apply_filters( 'monsterinsights_temporarily_hide_php_54_and_55_upgrade_warnings', version_compare( phpversion(), '5.6', '<' ) ),
293
+ 'php_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-php/' ),
294
+ 'wp_version' => $wp_version,
295
+ 'wp_version_below_46' => version_compare( $wp_version, '4.6', '<' ),
296
+ 'wp_version_below_49' => version_compare( $wp_version, '4.9', '<' ),
297
+ 'wp_update_link' => monsterinsights_get_url( 'settings-notice', 'settings-page', 'https://www.monsterinsights.com/docs/update-wordpress/' ),
298
+ ),
299
+ 'plugin_version' => MONSTERINSIGHTS_VERSION,
300
+ 'is_admin' => true,
301
+ 'wizard_url' => admin_url( 'index.php?page=monsterinsights-onboarding' ),
302
+ )
303
+ );
304
+
305
+ return;
306
+ }
307
+ // ublock notice
308
+ add_action( 'admin_print_footer_scripts', 'monsterinsights_settings_ublock_error_js', 9999999 );
309
+ }
310
+
311
+ add_action( 'admin_enqueue_scripts', 'monsterinsights_admin_scripts' );
312
+
313
+ /**
314
+ * Remove Assets that conflict with ours from our screens.
315
+ *
316
+ * @return null Return early if not on the proper screen.
317
+ * @since 6.0.4
318
+ * @access public
319
+ *
320
+ */
321
+ function monsterinsights_remove_conflicting_asset_files() {
322
+
323
+ // Get current screen.
324
+ $screen = get_current_screen();
325
+
326
+ // Bail if we're not on a MonsterInsights screen.
327
+ if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
328
+ return;
329
+ }
330
+
331
+ $styles = array(
332
+ 'kt_admin_css', // Pinnacle theme
333
+ 'select2-css', // Schema theme
334
+ 'tweetshare_style', // TweetShare - Click To Tweet
335
+ 'tweetshare_custom_style', // TweetShare - Click To Tweet
336
+ 'tweeetshare_custome_style', // TweetShare - Click To Tweet
337
+ 'tweeetshare_notice_style', // TweetShare - Click To Tweet
338
+ 'tweeetshare_theme_style', // TweetShare - Click To Tweet
339
+ 'tweeetshare_tweet_box_style', // TweetShare - Click To Tweet
340
+ 'soultype2-admin', // SoulType Plugin
341
+ 'thesis-options-stylesheet', // Thesis Options Stylesheet
342
+ 'imagify-sweetalert-core', // Imagify
343
+ 'imagify-sweetalert', // Imagify
344
+ 'smls-backend-style', // Smart Logo Showcase Lite
345
+ 'wp-reactjs-starter', // wp-real-media-library
346
+ 'control-panel-modal-plugin', // Ken Theme
347
+ 'theme-admin-css', // Vitrine Theme
348
+ 'qi-framework-styles', // Artisan Nayma Theme
349
+ 'artisan-pages-style', // Artisan Pages Plugin
350
+ 'control-panel-modal-plugin', // Ken Theme
351
+ 'sweetalert', // Church Suite Theme by Webnus
352
+ 'woo_stock_alerts_admin_css', // WooCommerce bolder product alerts
353
+ 'custom_wp_admin_css', // Fix for Add Social Share
354
+ 'fo_css', // Fix for Add Social Share
355
+ 'font_css', // Fix for Add Social Share
356
+ 'font2_css', // Fix for Add Social Share
357
+ 'font3_css', // Fix for Add Social Share
358
+ 'hover_css', // Fix for Add Social Share
359
+ 'fontend_styling', // Fix for Add Social Share
360
+ 'datatable', // WP Todo
361
+ 'bootstrap', // WP Todo
362
+ 'flipclock', // WP Todo
363
+ 'repuso_css_admin', // Social testimonials and reviews by Repuso
364
+ );
365
+
366
+ $scripts = array(
367
+ 'kad_admin_js', // Pinnacle theme
368
+ 'dt-chart', // DesignThemes core features plugin
369
+ 'tweeetshare_font_script', // TweetShare - Click To Tweet
370
+ 'tweeetshare_jquery_script', // TweetShare - Click To Tweet
371
+ 'tweeetshare_jqueryui_script', // TweetShare - Click To Tweet
372
+ 'tweeetshare_custom_script', // TweetShare - Click To Tweet
373
+ 'imagify-promise-polyfill', // Imagify
374
+ 'imagify-sweetalert', // Imagify
375
+ 'imagify-chart', // Imagify
376
+ 'chartjs', // Comet Cache Pro
377
+ 'wp-reactjs-starter', // wp-real-media-library
378
+ 'jquery-tooltipster', // WP Real Media Library
379
+ 'jquery-nested-sortable', // WP Real Media Library
380
+ 'jquery-aio-tree', // WP Real Media Library
381
+ 'wp-media-picker', // WP Real Media Library
382
+ 'rml-general', // WP Real Media Library
383
+ 'rml-library', // WP Real Media Library
384
+ 'rml-grid', // WP Real Media Library
385
+ 'rml-list', // WP Real Media Library
386
+ 'rml-modal', // WP Real Media Library
387
+ 'rml-order', // WP Real Media Library
388
+ 'rml-meta', // WP Real Media Library
389
+ 'rml-uploader', // WP Real Media Library
390
+ 'rml-options', // WP Real Media Library
391
+ 'rml-usersettings', // WP Real Media Library
392
+ 'rml-main', // WP Real Media Library
393
+ 'control-panel-sweet-alert', // Ken Theme
394
+ 'sweet-alert-js', // Vitrine Theme
395
+ 'theme-admin-script', // Vitrine Theme
396
+ 'sweetalert', // Church Suite Theme by Webnus
397
+ 'be_alerts_charts', // WooCommerce bolder product alerts
398
+ 'magayo-lottery-results', // Magayo Lottery Results
399
+ 'control-panel-sweet-alert', // Ken Theme
400
+ 'cpm_chart', // WP Project Manager
401
+ 'adminscripts', // Artisan Nayma Theme
402
+ 'artisan-pages-script', // Artisan Pages Plugin
403
+ 'tooltipster', // Grand News Theme
404
+ 'fancybox', // Grand News Theme
405
+ 'grandnews-admin-cript', // Grand News Theme
406
+ 'colorpicker', // Grand News Theme
407
+ 'eye', // Grand News Theme
408
+ 'icheck', // Grand News Theme
409
+ 'learn-press-chart', // LearnPress
410
+ 'theme-script-main', // My Listing Theme by 27collective
411
+ 'selz', // Selz eCommerce
412
+ 'tie-admin-scripts', // Tie Theme
413
+ 'blossomthemes-toolkit', // BlossomThemes Toolkit
414
+ 'illdy-widget-upload-image', // Illdy Companion By Colorlib
415
+ 'moment.js', // WooCommerce Table Rate Shipping
416
+ 'default', // Bridge Theme
417
+ 'qode-tax-js', // Bridge Theme
418
+ 'wc_smartship_moment_js', // WooCommerce Posti SmartShip by markup.fi
419
+ 'ecwid-admin-js', // Fixes Conflict for Ecwid Shopping Cart
420
+ 'td-wp-admin-js', // Newspaper by tagDiv
421
+ 'moment', // Screets Live Chat
422
+ 'wpmf-base', // WP Media Folder Fix
423
+ 'wpmf-media-filters', // WP Media Folder Fix
424
+ 'wpmf-folder-tree', // WP Media Folder Fix
425
+ 'wpmf-assign-tree', // WP Media Folder Fix
426
+ 'js_files_for_wp_admin', // TagDiv Composer Fix
427
+ 'tdb_js_files_for_wp_admin_last', // TagDiv Composer Fix
428
+ 'tdb_js_files_for_wp_admin', // TagDiv Composer Fix
429
+ 'wd-functions', // affiliate boxes
430
+ 'ellk-aliExpansion', // Ali Dropship Plugin
431
+ 'ftmetajs', // Houzez Theme
432
+ 'qode_admin_default', // Fix For Stockholm Theme
433
+ 'qodef-tax-js', // Fix for Prowess Theme
434
+ 'qodef-user-js', // Fix for Prowess Theme
435
+ 'qodef-ui-admin', // Fix for Prowess Theme
436
+ 'ssi_script', // Fix for Add Social Share
437
+ 'live_templates', // Fix for Add Social Share
438
+ 'default', // Fix for Add Social Share
439
+ 'handsontable', // Fix WP Tables
440
+ 'moment-js', // Magee Shortcodes
441
+ 'postbox', // Scripts from wp-admin enqueued everywhere by WP Posts Filter
442
+ 'link', // Scripts from wp-admin enqueued everywhere by WP Posts Filter
443
+ 'wpvr_scripts', // WP Video Robot
444
+ 'wpvr_scripts_loaded', // WP Video Robot
445
+ 'wpvr_scripts_assets', // WP Video Robot
446
+ 'writee_widget_admin', // Fix for the Writtee theme
447
+ '__ytprefs_admin__', // Fix for YouTube by EmbedPlus plugin
448
+ 'momentjs', // Fix for Blog Time plugin
449
+ 'c2c_BlogTime', // Fix for Blog Time plugin
450
+ 'material-wp', // Fix for MaterialWP plugin
451
+ 'wp-color-picker-alpha', // Fix for MaterialWP plugin
452
+ 'grandtour-theme-script', // Grandtour Theme
453
+ 'swifty-img-widget-admin-script', // Fix for Swifty Image Widget
454
+ 'datatable', // WP Todo
455
+ 'flipclock', // WP Todo
456
+ 'bootstrap', // WP Todo
457
+ 'repuso_js_admin', // Social testimonials and reviews by Repuso
458
+ 'chart', // Video Mate Pro Theme
459
+ 'reuse_vendor', // RedQ Reuse Form
460
+ 'jetpack-onboarding-vendor', // Jetpack Onboarding Bluehost
461
+ 'date-js', // Google Analytics by Web Dorado
462
+ );
463
+
464
+ if ( ! empty( $styles ) ) {
465
+ foreach ( $styles as $style ) {
466
+ wp_dequeue_style( $style ); // Remove CSS file from MI screen
467
+ wp_deregister_style( $style );
468
+ }
469
+ }
470
+ if ( ! empty( $scripts ) ) {
471
+ foreach ( $scripts as $script ) {
472
+ wp_dequeue_script( $script ); // Remove JS file from MI screen
473
+ wp_deregister_script( $script );
474
+ }
475
+ }
476
+
477
+ $third_party = array(
478
+ 'select2',
479
+ 'sweetalert',
480
+ 'clipboard',
481
+ 'matchHeight',
482
+ 'inputmask',
483
+ 'jquery-confirm',
484
+ 'list',
485
+ 'toastr',
486
+ 'tooltipster',
487
+ 'flag-icon',
488
+ 'bootstrap',
489
+ );
490
+
491
+ global $wp_styles;
492
+ foreach ( $wp_styles->queue as $handle ) {
493
+ if ( strpos( $wp_styles->registered[ $handle ]->src, 'wp-content' ) === false ) {
494
+ return;
495
+ }
496
+
497
+ if ( strpos( $wp_styles->registered[ $handle ]->handle, 'monsterinsights' ) !== false ) {
498
+ return;
499
+ }
500
+
501
+ foreach ( $third_party as $partial ) {
502
+ if ( strpos( $wp_styles->registered[ $handle ]->handle, $partial ) !== false ) {
503
+ wp_dequeue_style( $handle ); // Remove css file from MI screen
504
+ wp_deregister_style( $handle );
505
+ break;
506
+ } else if ( strpos( $wp_styles->registered[ $handle ]->src, $partial ) !== false ) {
507
+ wp_dequeue_style( $handle ); // Remove css file from MI screen
508
+ wp_deregister_style( $handle );
509
+ break;
510
+ }
511
+ }
512
+ }
513
+
514
+ global $wp_scripts;
515
+ foreach ( $wp_scripts->queue as $handle ) {
516
+ if ( strpos( $wp_scripts->registered[ $handle ]->src, 'wp-content' ) === false ) {
517
+ return;
518
+ }
519
+
520
+ if ( strpos( $wp_scripts->registered[ $handle ]->handle, 'monsterinsights' ) !== false ) {
521
+ return;
522
+ }
523
+
524
+ foreach ( $third_party as $partial ) {
525
+ if ( strpos( $wp_scripts->registered[ $handle ]->handle, $partial ) !== false ) {
526
+ wp_dequeue_script( $handle ); // Remove JS file from MI screen
527
+ wp_deregister_script( $handle );
528
+ break;
529
+ } else if ( strpos( $wp_scripts->registered[ $handle ]->src, $partial ) !== false ) {
530
+ wp_dequeue_script( $handle ); // Remove JS file from MI screen
531
+ wp_deregister_script( $handle );
532
+ break;
533
+ }
534
+ }
535
+ }
536
+
537
+ // Remove actions from themes that are not following best practices and break the admin doing so
538
+ // Theme: Newspaper by tagDiv
539
+ remove_action( 'admin_enqueue_scripts', 'load_wp_admin_js' );
540
+ remove_action( 'admin_enqueue_scripts', 'load_wp_admin_css' );
541
+ remove_action( 'admin_print_scripts-widgets.php', 'td_on_admin_print_scripts_farbtastic' );
542
+ remove_action( 'admin_print_styles-widgets.php', 'td_on_admin_print_styles_farbtastic' );
543
+ remove_action( 'admin_print_footer_scripts', 'check_if_media_uploads_is_loaded', 9999 );
544
+ remove_action( 'print_media_templates', 'td_custom_gallery_settings_hook' );
545
+ remove_action( 'print_media_templates', 'td_change_backbone_js_hook' );
546
+ remove_action( 'admin_head', 'tdc_on_admin_head' ); // TagDiv Composer Fix
547
+ remove_action( 'print_media_templates', 'us_media_templates' ); // Impreza Theme Fix
548
+ remove_action( 'admin_footer', 'gt3pg_add_gallery_template' ); // GT3 Photo & Video Gallery By GT3 Themes Plugin Fix
549
+ // Plugin WP Booklist:
550
+ remove_action( 'admin_footer', 'wpbooklist_jre_dismiss_prem_notice_forever_action_javascript' );
551
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_add_book_action_javascript' );
552
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_show_form_action_javascript' );
553
+ remove_action( 'admin_footer', 'wpbooklist_show_book_in_colorbox_action_javascript' );
554
+ remove_action( 'admin_footer', 'wpbooklist_new_lib_shortcode_action_javascript' );
555
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_save_library_display_options_action_javascript' );
556
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_save_post_display_options_action_javascript' );
557
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_save_page_display_options_action_javascript' );
558
+ remove_action( 'admin_footer', 'wpbooklist_update_display_options_action_javascript' );
559
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_pagination_action_javascript' );
560
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_switch_lib_action_javascript' );
561
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_search_action_javascript' );
562
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_actual_action_javascript' );
563
+ remove_action( 'admin_footer', 'wpbooklist_delete_book_action_javascript' );
564
+ remove_action( 'admin_footer', 'wpbooklist_user_apis_action_javascript' );
565
+ remove_action( 'admin_footer', 'wpbooklist_upload_new_stylepak_action_javascript' );
566
+ remove_action( 'admin_footer', 'wpbooklist_upload_new_post_template_action_javascript' );
567
+ remove_action( 'admin_footer', 'wpbooklist_upload_new_page_template_action_javascript' );
568
+ remove_action( 'admin_footer', 'wpbooklist_create_db_library_backup_action_javascript' );
569
+ remove_action( 'admin_footer', 'wpbooklist_restore_db_library_backup_action_javascript' );
570
+ remove_action( 'admin_footer', 'wpbooklist_create_csv_action_javascript' );
571
+ remove_action( 'admin_footer', 'wpbooklist_amazon_localization_action_javascript' );
572
+ remove_action( 'admin_footer', 'wpbooklist_delete_book_bulk_action_javascript' );
573
+ remove_action( 'admin_footer', 'wpbooklist_reorder_action_javascript' );
574
+ remove_action( 'admin_footer', 'wpbooklist_exit_results_action_javascript' );
575
+ remove_action( 'admin_footer', 'wpbooklist_storytime_select_category_action_javascript' );
576
+ remove_action( 'admin_footer', 'wpbooklist_storytime_get_story_action_javascript' );
577
+ remove_action( 'admin_footer', 'wpbooklist_storytime_expand_browse_action_javascript' );
578
+ remove_action( 'admin_footer', 'wpbooklist_storytime_save_settings_action_javascript' );
579
+ remove_action( 'admin_footer', 'wpbooklist_delete_story_action_javascript' );
580
+ }
581
+
582
+ add_action( 'admin_enqueue_scripts', 'monsterinsights_remove_conflicting_asset_files', 9999 );
583
+
584
+ /**
585
+ * Remove non-MI notices from MI page.
586
+ *
587
+ * @return null Return early if not on the proper screen.
588
+ * @since 6.0.0
589
+ * @access public
590
+ *
591
+ */
592
+ function hide_non_monsterinsights_warnings() {
593
+ // Bail if we're not on a MonsterInsights screen.
594
+ if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], 'monsterinsights' ) === false ) {
595
+ return;
596
+ }
597
+
598
+ global $wp_filter;
599
+ if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
600
+ foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
601
+ foreach ( $hooks as $name => $arr ) {
602
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
603
+ unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
604
+ continue;
605
+ }
606
+ if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'monsterinsights' ) !== false ) {
607
+ continue;
608
+ }
609
+ if ( ! empty( $name ) && strpos( $name, 'monsterinsights' ) === false ) {
610
+ unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
611
+ }
612
+ }
613
+ }
614
+ }
615
+
616
+ if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
617
+ foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
618
+ foreach ( $hooks as $name => $arr ) {
619
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
620
+ unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
621
+ continue;
622
+ }
623
+ if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'monsterinsights' ) !== false ) {
624
+ continue;
625
+ }
626
+ if ( ! empty( $name ) && strpos( $name, 'monsterinsights' ) === false ) {
627
+ unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
628
+ }
629
+ }
630
+ }
631
+ }
632
+
633
+ if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
634
+ foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
635
+ foreach ( $hooks as $name => $arr ) {
636
+ if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) {
637
+ unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
638
+ continue;
639
+ }
640
+ if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'monsterinsights' ) !== false ) {
641
+ continue;
642
+ }
643
+ if ( ! empty( $name ) && strpos( $name, 'monsterinsights' ) === false ) {
644
+ unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
645
+ }
646
+ }
647
+ }
648
+ }
649
+ }
650
+
651
+ add_action( 'admin_print_scripts', 'hide_non_monsterinsights_warnings' );
652
+ add_action( 'admin_head', 'hide_non_monsterinsights_warnings', PHP_INT_MAX );
653
+
654
+ /**
655
+ * Called whenever an upgrade button / link is displayed in Lite, this function will
656
+ * check if there's a shareasale ID specified.
657
+ *
658
+ * There are three ways to specify an ID, ordered by highest to lowest priority
659
+ * - add_filter( 'monsterinsights_shareasale_id', function() { return 1234; } );
660
+ * - define( 'MONSTERINSIGHTS_SHAREASALE_ID', 1234 );
661
+ * - get_option( 'monsterinsights_shareasale_id' ); (with the option being in the wp_options table)
662
+ *
663
+ * If an ID is present, returns the ShareASale link with the affiliate ID, and tells
664
+ * ShareASale to then redirect to monsterinsights.com/lite
665
+ *
666
+ * If no ID is present, just returns the monsterinsights.com/lite URL with UTM tracking.
667
+ *
668
+ * @return string Upgrade link.
669
+ * @since 6.0.0
670
+ * @access public
671
+ *
672
+ */
673
+ function monsterinsights_get_upgrade_link( $medium = '', $campaign = '', $url = '' ) {
674
+ $url = monsterinsights_get_url( $medium, $campaign, $url, false );
675
+
676
+ if ( monsterinsights_is_pro_version() ) {
677
+ return esc_url( $url );
678
+ }
679
+
680
+ // Get the ShareASale ID
681
+ $shareasale_id = monsterinsights_get_shareasale_id();
682
+
683
+ // If we have a shareasale ID return the shareasale url
684
+ if ( ! empty( $shareasale_id ) ) {
685
+ $shareasale_id = absint( $shareasale_id );
686
+
687
+ return esc_url( monsterinsights_get_shareasale_url( $shareasale_id, $url ) );
688
+ } else {
689
+ return esc_url( $url );
690
+ }
691
+ }
692
+
693
+ function monsterinsights_get_url( $medium = '', $campaign = '', $url = '', $escape = true ) {
694
+ // Setup Campaign variables
695
+ $source = monsterinsights_is_pro_version() ? 'proplugin' : 'liteplugin';
696
+ $medium = ! empty( $medium ) ? $medium : 'defaultmedium';
697
+ $campaign = ! empty( $campaign ) ? $campaign : 'defaultcampaign';
698
+ $content = MONSTERINSIGHTS_VERSION;
699
+ $default_url = monsterinsights_is_pro_version() ? '' : 'lite/';
700
+ $url = ! empty( $url ) ? $url : 'https://www.monsterinsights.com/' . $default_url;
701
+
702
+ // Put together redirect URL
703
+ $url = add_query_arg(
704
+ array(
705
+ 'utm_source' => $source, // Pro/Lite Plugin
706
+ 'utm_medium' => sanitize_key( $medium ), // Area of MonsterInsights (example Reports)
707
+ 'utm_campaign' => sanitize_key( $campaign ), // Which link (example eCommerce Report)
708
+ 'utm_content' => $content, // Version number of MI
709
+ ),
710
+ trailingslashit( $url )
711
+ );
712
+
713
+ if ( $escape ) {
714
+ return esc_url( $url );
715
+ } else {
716
+ return $url;
717
+ }
718
+ }
719
+
720
+ function monsterinsights_settings_ublock_error_js() {
721
+ echo "<script type='text/javascript'>\n";
722
+ echo "jQuery( document ).ready( function( $ ) {
723
+ if ( window.uorigindetected == null){
724
+ $('#monsterinsights-ublock-origin-error').show();
725
+ $('.monsterinsights-nav-tabs').hide();
726
+ $('.monsterinsights-nav-container').hide();
727
+ $('#monsterinsights-addon-heading').hide();
728
+ $('#monsterinsights-addons').hide();
729
+ $('#monsterinsights-reports').hide();
730
+ }
731
+ });";
732
+ echo "\n</script>";
733
+ }
734
+
735
+ function monsterinsights_ublock_notice() {
736
+ ob_start(); ?>
737
+ <div id="monsterinsights-ublock-origin-error" class="error inline" style="display:none;">
738
+ <?php echo sprintf( esc_html__( 'MonsterInsights has detected that it\'s files are being blocked. This is usually caused by a adblock browser plugin (particularly uBlock Origin), or a conflicting WordPress theme or plugin. This issue only affects the admin side of MonsterInsights. To solve this, ensure MonsterInsights is whitelisted for your website URL in any adblock browser plugin you use. For step by step directions on how to do this, %1$sclick here%2$s. If this doesn\'t solve the issue (rare), send us a ticket %3$shere%2$s and we\'ll be happy to help diagnose the issue.', 'google-analytics-for-wordpress' ), '<a href="https://monsterinsights.com/docs/monsterinsights-asset-files-blocked/" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>', '<a href="https://monsterinsights.com/contact/" target="_blank" rel="noopener noreferrer" referrer="no-referrer">' );
739
+ ?>
740
+ </div>
741
+ <?php
742
+ return ob_get_clean();
743
+ }
744
+
745
+ /**
746
+ * Some themes/plugins don't add proper checks and load JS code in all admin pages causing conflicts.
747
+ */
748
+ function monsterinsights_remove_unnecessary_footer_hooks() {
749
+
750
+ $screen = get_current_screen();
751
+ // Bail if we're not on a MonsterInsights screen.
752
+ if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
753
+ return;
754
+ }
755
+
756
+ // Remove js code added by Newspaper theme - version 8.8.0.
757
+ remove_action( 'print_media_templates', 'td_custom_gallery_settings_hook' );
758
+ remove_action( 'print_media_templates', 'td_change_backbone_js_hook' );
759
+ // Remove js code added by the Brooklyn theme - version 4.5.3.1.
760
+ remove_action( 'print_media_templates', 'ut_create_gallery_options' );
761
+
762
+ // Remove js code added by WordPress Book List Plugin - version 5.8.1.
763
+ remove_action( 'admin_footer', 'wpbooklist_jre_dismiss_prem_notice_forever_action_javascript' );
764
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_add_book_action_javascript' );
765
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_show_form_action_javascript' );
766
+ remove_action( 'admin_footer', 'wpbooklist_show_book_in_colorbox_action_javascript' );
767
+ remove_action( 'admin_footer', 'wpbooklist_new_lib_shortcode_action_javascript' );
768
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_save_library_display_options_action_javascript' );
769
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_save_post_display_options_action_javascript' );
770
+ remove_action( 'admin_footer', 'wpbooklist_dashboard_save_page_display_options_action_javascript' );
771
+ remove_action( 'admin_footer', 'wpbooklist_update_display_options_action_javascript' );
772
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_pagination_action_javascript' );
773
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_switch_lib_action_javascript' );
774
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_search_action_javascript' );
775
+ remove_action( 'admin_footer', 'wpbooklist_edit_book_actual_action_javascript' );
776
+ remove_action( 'admin_footer', 'wpbooklist_delete_book_action_javascript' );
777
+ remove_action( 'admin_footer', 'wpbooklist_user_apis_action_javascript' );
778
+ remove_action( 'admin_footer', 'wpbooklist_upload_new_stylepak_action_javascript' );
779
+ remove_action( 'admin_footer', 'wpbooklist_upload_new_post_template_action_javascript' );
780
+ remove_action( 'admin_footer', 'wpbooklist_upload_new_page_template_action_javascript' );
781
+ remove_action( 'admin_footer', 'wpbooklist_create_db_library_backup_action_javascript' );
782
+ remove_action( 'admin_footer', 'wpbooklist_restore_db_library_backup_action_javascript' );
783
+ remove_action( 'admin_footer', 'wpbooklist_create_csv_action_javascript' );
784
+ remove_action( 'admin_footer', 'wpbooklist_amazon_localization_action_javascript' );
785
+ remove_action( 'admin_footer', 'wpbooklist_delete_book_bulk_action_javascript' );
786
+ remove_action( 'admin_footer', 'wpbooklist_reorder_action_javascript' );
787
+ remove_action( 'admin_footer', 'wpbooklist_exit_results_action_javascript' );
788
+ remove_action( 'admin_footer', 'wpbooklist_storytime_select_category_action_javascript' );
789
+ remove_action( 'admin_footer', 'wpbooklist_storytime_get_story_action_javascript' );
790
+ remove_action( 'admin_footer', 'wpbooklist_storytime_expand_browse_action_javascript' );
791
+ remove_action( 'admin_footer', 'wpbooklist_storytime_save_settings_action_javascript' );
792
+ remove_action( 'admin_footer', 'wpbooklist_delete_story_action_javascript' );
793
+ }
794
+
795
+ add_action( 'admin_head', 'monsterinsights_remove_unnecessary_footer_hooks', 15 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
includes/admin/licensing/autoupdate.php CHANGED
@@ -1,94 +1,94 @@
1
- <?php
2
- /**
3
- * Filters the auto update plugin routine to allow MonsterInsights to be
4
- * automatically updated.
5
- *
6
- * @since 6.3.0
7
- *
8
- * @param bool $update Flag to update the plugin or not.
9
- * @param array $item Update data about a specific plugin.
10
- * @return bool $update The new update state.
11
- */
12
- function monsterinsights_automatic_updates( $update, $item ) {
13
-
14
- // If this is multisite and is not on the main site, return early.
15
- if ( is_multisite() && ! is_main_site() ) {
16
- return $update;
17
- }
18
-
19
- // If we don't have everything we need, return early.
20
- $item = (array) $item;
21
- if ( ! isset( $item['new_version'] ) || ! isset( $item['slug'] ) ) {
22
- return $update;
23
- }
24
-
25
- // If the plugin isn't ours, return early.
26
- $is_free = 'google-analytics-for-wordpress' === $item['slug'];
27
- $is_paid = isset( $item['monsterinsights_plugin'] ); // see updater class
28
- if ( ! $is_free && ! $is_paid ) {
29
- return $update;
30
- }
31
-
32
- $version = $is_free ? MONSTERINSIGHTS_LITE_VERSION : $item['old_version'];
33
- $automatic_updates = monsterinsights_get_option( 'automatic_updates', false );
34
- $current_major = monsterinsights_get_major_version( $version );
35
- $new_major = monsterinsights_get_major_version( $item['new_version'] );
36
-
37
- // If the opt in update allows major updates but there is no major version update, return early.
38
- if ( $current_major < $new_major ) {
39
- if ( $automatic_updates === 'all' ) {
40
- return true;
41
- } else {
42
- return $update;
43
- }
44
- }
45
-
46
- // If the opt in update allows minor updates but there is no minor version update, return early.
47
- if ( $current_major == $new_major ) {
48
- if ( $automatic_updates === 'all' || $automatic_updates === 'minor' ) {
49
- return true;
50
- } else {
51
- return $update;
52
- }
53
- }
54
-
55
- // All our checks have passed - this plugin can be updated!
56
- return true;
57
- }
58
-
59
- add_filter( 'auto_update_plugin', 'monsterinsights_automatic_updates', 10, 2 );
60
- /**
61
- * Notes about autoupdater:
62
- * This runs on the normal WordPress auto-update sequence:
63
- * 1. In wp-includes/update.php, wp_version_check() is called by the WordPress update cron (every 8 or 12 hours; can be overriden to be faster/long or turned off by plugins)
64
- * 2. In wp-includes/update.php, wp_version_check() ends with a action call to do_action( 'wp_maybe_auto_update' ) if cron is running
65
- * 3. In wp-includes/update.php, wp_maybe_auto_update() hooks into wp_maybe_auto_update action, creates a new WP_Automatic_Updater instance and calls WP_Automatic_Updater->run
66
- * 4. In wp-admin/includes/class-wp-automatic-updater.php $this->run() checks to make sure we're on the main site if on a network, and also if the autoupdates are disabled (by plugin, by being on a version controlled site, etc )
67
- * 5. In wp-admin/includes/class-wp-automatic-updater.php $this->run() then checks to see which plugins have new versions (version/update check)
68
- * 6. In wp-admin/includes/class-wp-automatic-updater.php $this->run() then calls $this->update() for each plugin installed who has an upgrade.
69
- * 7 In wp-admin/includes/class-wp-automatic-updater.php $this->update() double checks filesystem access and then installs the plugin if able
70
- *
71
- * Notes:
72
- * - This autoupdater only works if WordPress core detects no version control. If you want to test this, do it on a new WP site without any .git folders anywhere.
73
- * - This autoupdater only works if the file access is able to be written to
74
- * - This autoupdater only works if a new version has been detected, and will run not the second the update is released, but whenever the cron for wp_version_check is next released. This is generally run every 8-12 hours.
75
- * - However, that cron can be disabled, the autoupdater can be turned off via constant or filter, version control or file lock can be detected, and other plugins can be installed (incl in functions of theme) that turn off all
76
- * all automatic plugin updates.
77
- * - If you want to test this is working, you have to manually run the wp_version_check cron. Install the WP Crontrol plugin or Core Control plugin, and run the cron manually using it.
78
- * - Again, because you skimmed over it the first time, if you want to test this manually you need to test this on a new WP install without version control for core, plugins, etc, without file lock, with license key entered (for pro only)
79
- * and use the WP Crontrol or Core Control plugin to run wp_version_check
80
- * - You may have to manually remove an option called "auto_update.lock" from the WP options table
81
- * - You may need to run wp_version_check multiple times (note though that they must be spaced at least 60 seconds apart)
82
- * - Because WP's updater asks the OS if the file is writable, make sure you do not have any files/folders for the plugin you are trying to autoupdate open when testing.
83
- * - You may need to delete the plugin info transient to get it to hard refresh the plugin info.
84
- */
85
-
86
-
87
- function monsterinsights_get_major_version( $version ) {
88
- $exploded_version = explode( '.', $version );
89
- if ( isset( $exploded_version[2] ) ) {
90
- return $exploded_version[0] . '.' . $exploded_version[1] . '.' . $exploded_version[2];
91
- } else {
92
- return $exploded_version[0] . '.' . $exploded_version[1] . '.0';
93
- }
94
  }
1
+ <?php
2
+ /**
3
+ * Filters the auto update plugin routine to allow MonsterInsights to be
4
+ * automatically updated.
5
+ *
6
+ * @since 6.3.0
7
+ *
8
+ * @param bool $update Flag to update the plugin or not.
9
+ * @param array $item Update data about a specific plugin.
10
+ * @return bool $update The new update state.
11
+ */
12
+ function monsterinsights_automatic_updates( $update, $item ) {
13
+
14
+ // If this is multisite and is not on the main site, return early.
15
+ if ( is_multisite() && ! is_main_site() ) {
16
+ return $update;
17
+ }
18
+
19
+ // If we don't have everything we need, return early.
20
+ $item = (array) $item;
21
+ if ( ! isset( $item['new_version'] ) || ! isset( $item['slug'] ) ) {
22
+ return $update;
23
+ }
24
+
25
+ // If the plugin isn't ours, return early.
26
+ $is_free = 'google-analytics-for-wordpress' === $item['slug'];
27
+ $is_paid = isset( $item['monsterinsights_plugin'] ); // see updater class
28
+ if ( ! $is_free && ! $is_paid ) {
29
+ return $update;
30
+ }
31
+
32
+ $version = $is_free ? MONSTERINSIGHTS_LITE_VERSION : $item['old_version'];
33
+ $automatic_updates = monsterinsights_get_option( 'automatic_updates', false );
34
+ $current_major = monsterinsights_get_major_version( $version );
35
+ $new_major = monsterinsights_get_major_version( $item['new_version'] );
36
+
37
+ // If the opt in update allows major updates but there is no major version update, return early.
38
+ if ( $current_major < $new_major ) {
39
+ if ( $automatic_updates === 'all' ) {
40
+ return true;
41
+ } else {
42
+ return $update;
43
+ }
44
+ }
45
+
46
+ // If the opt in update allows minor updates but there is no minor version update, return early.
47
+ if ( $current_major == $new_major ) {
48
+ if ( $automatic_updates === 'all' || $automatic_updates === 'minor' ) {
49
+ return true;
50
+ } else {
51
+ return $update;
52
+ }
53
+ }
54
+
55
+ // All our checks have passed - this plugin can be updated!
56
+ return true;
57
+ }
58
+
59
+ add_filter( 'auto_update_plugin', 'monsterinsights_automatic_updates', 10, 2 );
60
+ /**
61
+ * Notes about autoupdater:
62
+ * This runs on the normal WordPress auto-update sequence:
63
+ * 1. In wp-includes/update.php, wp_version_check() is called by the WordPress update cron (every 8 or 12 hours; can be overriden to be faster/long or turned off by plugins)
64
+ * 2. In wp-includes/update.php, wp_version_check() ends with a action call to do_action( 'wp_maybe_auto_update' ) if cron is running
65
+ * 3. In wp-includes/update.php, wp_maybe_auto_update() hooks into wp_maybe_auto_update action, creates a new WP_Automatic_Updater instance and calls WP_Automatic_Updater->run
66
+ * 4. In wp-admin/includes/class-wp-automatic-updater.php $this->run() checks to make sure we're on the main site if on a network, and also if the autoupdates are disabled (by plugin, by being on a version controlled site, etc )
67
+ * 5. In wp-admin/includes/class-wp-automatic-updater.php $this->run() then checks to see which plugins have new versions (version/update check)
68
+ * 6. In wp-admin/includes/class-wp-automatic-updater.php $this->run() then calls $this->update() for each plugin installed who has an upgrade.
69
+ * 7 In wp-admin/includes/class-wp-automatic-updater.php $this->update() double checks filesystem access and then installs the plugin if able
70
+ *
71
+ * Notes:
72
+ * - This autoupdater only works if WordPress core detects no version control. If you want to test this, do it on a new WP site without any .git folders anywhere.
73
+ * - This autoupdater only works if the file access is able to be written to
74
+ * - This autoupdater only works if a new version has been detected, and will run not the second the update is released, but whenever the cron for wp_version_check is next released. This is generally run every 8-12 hours.
75
+ * - However, that cron can be disabled, the autoupdater can be turned off via constant or filter, version control or file lock can be detected, and other plugins can be installed (incl in functions of theme) that turn off all
76
+ * all automatic plugin updates.
77
+ * - If you want to test this is working, you have to manually run the wp_version_check cron. Install the WP Crontrol plugin or Core Control plugin, and run the cron manually using it.
78
+ * - Again, because you skimmed over it the first time, if you want to test this manually you need to test this on a new WP install without version control for core, plugins, etc, without file lock, with license key entered (for pro only)
79
+ * and use the WP Crontrol or Core Control plugin to run wp_version_check
80
+ * - You may have to manually remove an option called "auto_update.lock" from the WP options table
81
+ * - You may need to run wp_version_check multiple times (note though that they must be spaced at least 60 seconds apart)
82
+ * - Because WP's updater asks the OS if the file is writable, make sure you do not have any files/folders for the plugin you are trying to autoupdate open when testing.
83
+ * - You may need to delete the plugin info transient to get it to hard refresh the plugin info.
84
+ */
85
+
86
+
87
+ function monsterinsights_get_major_version( $version ) {
88
+ $exploded_version = explode( '.', $version );
89
+ if ( isset( $exploded_version[2] ) ) {
90
+ return $exploded_version[0] . '.' . $exploded_version[1] . '.' . $exploded_version[2];
91
+ } else {
92
+ return $exploded_version[0] . '.' . $exploded_version[1] . '.0';
93
+ }
94
  }
includes/admin/licensing/license-actions.php DELETED
@@ -1,547 +0,0 @@
1
- <?php
2
- /**
3
- * License Actions class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
- final class MonsterInsights_License_Actions {
17
- /**
18
- * Holds the license key.
19
- *
20
- * @since 6.0.0
21
- *
22
- * @var string
23
- */
24
- public $key;
25
-
26
- /**
27
- * Holds any license error messages.
28
- *
29
- * @since 6.0.0
30
- *
31
- * @var array
32
- */
33
- public $errors = array();
34
-
35
- /**
36
- * Holds any license success messages.
37
- *
38
- * @since 6.0.0
39
- *
40
- * @var array
41
- */
42
- public $success = array();
43
-
44
- /**
45
- * Primary class constructor.
46
- *
47
- * @since 6.0.0
48
- */
49
- public function __construct() {
50
- add_action( 'admin_init', array( $this, 'admin_init' ) );
51
-
52
- add_action( 'wp_ajax_monsterinsights_verify_license', array( $this, 'ajax_verify_key' ) );
53
-
54
- add_action( 'wp_ajax_monsterinsights_deactivate_license', array( $this, 'ajax_deactivate_key' ) );
55
-
56
- add_action( 'wp_ajax_monsterinsights_validate_license', array( $this, 'ajax_validate_key' ) );
57
- }
58
-
59
- public function admin_init() {
60
- // Possibly verify the key.
61
- $this->maybe_verify_key();
62
-
63
- // Add potential admin notices for actions around the admin.
64
- add_action( 'admin_notices', array( $this, 'monsterinsights_notices' ), 11 );
65
- add_action( 'network_admin_notices', array( $this, 'monsterinsights_notices' ), 11 );
66
-
67
- // Grab the license key. If it is not set (even after verification), return early.
68
- $this->key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
69
- if ( ! $this->key ) {
70
- return;
71
- }
72
-
73
- // Possibly handle validating, deactivating and refreshing license keys.
74
- $this->maybe_validate_key();
75
- $this->maybe_deactivate_key();
76
- $this->maybe_refresh_key();
77
- }
78
-
79
- /**
80
- * Maybe verifies a license key entered by the user.
81
- *
82
- * @since 6.0.0
83
- *
84
- * @return null Return early if the key fails to be verified.
85
- */
86
- public function maybe_verify_key() {
87
-
88
- if ( empty( $_POST['monsterinsights-license-key'] ) || strlen( $_POST['monsterinsights-license-key'] ) < 10 || empty( $_POST['monsterinsights-verify-submit'] ) ) {
89
- return;
90
- }
91
-
92
- if ( ! wp_verify_nonce( $_POST['monsterinsights-key-nonce'], 'monsterinsights-key-nonce' ) ) {
93
- return;
94
- }
95
-
96
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
97
- return;
98
- }
99
-
100
- $this->verify_key();
101
-
102
- }
103
-
104
- /**
105
- * Ajax handler for verifying the License key.
106
- */
107
- public function ajax_verify_key() {
108
-
109
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
110
-
111
- $network_admin = isset( $_POST['network'] ) && $_POST['network'];
112
- $license = ! empty( $_POST['license'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['license'] ) ) ) : false;
113
-
114
- if ( ! $license ) {
115
- wp_send_json_error(
116
- array(
117
- 'error' => esc_html__( 'Please enter a license key.', 'google-analytics-for-wordpress' ),
118
- )
119
- );
120
- }
121
-
122
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
123
- wp_send_json_error(
124
- array(
125
- 'error' => esc_html__( 'You are not allowed to verify a license key.', 'google-analytics-for-wordpress' ),
126
- )
127
- );
128
- }
129
-
130
- $forced = isset( $_POST['forced'] ) && 'true' === sanitize_text_field( wp_unslash( $_POST['forced'] ) );
131
-
132
- $verify = $this->perform_remote_request( 'verify-key', array( 'tgm-updater-key' => $license ) );
133
-
134
- if ( ! $verify ) {
135
- wp_send_json_error(
136
- array(
137
- 'error' => esc_html__( 'There was an error connecting to the remote key API. Please try again later.', 'google-analytics-for-wordpress' ),
138
- )
139
- );
140
- }
141
-
142
- if ( ! empty( $verify->error ) ) {
143
- wp_send_json_error(
144
- array(
145
- 'error' => $verify->error,
146
- )
147
- );
148
-
149
- }
150
-
151
- // Otherwise, our request has been done successfully. Update the option and set the success message.
152
- $option = $network_admin ? MonsterInsights()->license->get_network_license() : MonsterInsights()->license->get_site_license();
153
- $option['key'] = $license;
154
- $option['type'] = isset( $verify->type ) ? $verify->type : $option['type'];
155
- $option['is_expired'] = false;
156
- $option['is_disabled'] = false;
157
- $option['is_invalid'] = false;
158
-
159
- $network_admin ? MonsterInsights()->license->set_network_license( $option ) : MonsterInsights()->license->set_site_license( $option );
160
- delete_transient( '_monsterinsights_addons' );
161
- monsterinsights_get_addons_data( $option['key'] );
162
-
163
- $message = isset( $verify->success ) ? $verify->success : esc_html__( 'Congratulations! This site is now receiving automatic updates.', 'google-analytics-for-wordpress' );
164
-
165
- wp_send_json_success(
166
- array(
167
- 'message' => $message,
168
- 'license_type' => $option['type'],
169
- )
170
- );
171
-
172
- }
173
-
174
- /**
175
- * Verifies a license key entered by the user.
176
- *
177
- * @since 6.0.0
178
- */
179
- public function verify_key() {
180
-
181
- // Perform a request to verify the key.
182
- $verify = $this->perform_remote_request( 'verify-key', array( 'tgm-updater-key' => trim( $_POST['monsterinsights-license-key'] ) ) );
183
-
184
- // If it returns false, send back a generic error message and return.
185
- if ( ! $verify ) {
186
- $this->errors[] = esc_html__( 'There was an error connecting to the remote key API. Please try again later.', 'google-analytics-for-wordpress' );
187
-
188
- return;
189
- }
190
-
191
- // If an error is returned, set the error and return.
192
- if ( ! empty( $verify->error ) ) {
193
- $this->errors[] = $verify->error;
194
-
195
- return;
196
- }
197
-
198
- // Otherwise, our request has been done successfully. Update the option and set the success message.
199
- $option = is_network_admin() ? MonsterInsights()->license->get_network_license() : MonsterInsights()->license->get_site_license();
200
- $option['key'] = trim( $_POST['monsterinsights-license-key'] );
201
- $option['type'] = isset( $verify->type ) ? $verify->type : $option['type'];
202
- $option['is_expired'] = false;
203
- $option['is_disabled'] = false;
204
- $option['is_invalid'] = false;
205
- $this->success[] = isset( $verify->success ) ? $verify->success : esc_html__( 'Congratulations! This site is now receiving automatic updates.', 'google-analytics-for-wordpress' );
206
- is_network_admin() ? MonsterInsights()->license->set_network_license( $option ) : MonsterInsights()->license->set_site_license( $option );
207
- delete_transient( '_monsterinsights_addons' );
208
- monsterinsights_get_addons_data( $option['key'] );
209
- // Make sure users can now update their plugins if they previously an expired key.
210
- wp_clean_plugins_cache( true );
211
- }
212
-
213
- /**
214
- * Maybe validates a license key entered by the user.
215
- *
216
- * @since 6.0.0
217
- *
218
- * @return null Return early if the transient has not expired yet.
219
- */
220
- public function maybe_validate_key() {
221
- $check = is_network_admin() ? MonsterInsights()->license->time_to_check_network_license() : MonsterInsights()->license->time_to_check_site_license();
222
- if ( $check ) {
223
- $this->validate_key();
224
- }
225
- }
226
-
227
- /**
228
- * Ajax handler for validating the current key.
229
- */
230
- public function ajax_validate_key() {
231
-
232
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
233
-
234
- $this->validate_key( true );
235
-
236
- if ( ! empty( $this->errors ) ) {
237
- wp_send_json_error( array(
238
- 'error' => $this->errors[0],
239
- ) );
240
- }
241
-
242
- if ( ! empty( $this->success ) ) {
243
- wp_send_json_success(
244
- array(
245
- 'message' => $this->success[0],
246
- )
247
- );
248
- }
249
-
250
- wp_die();
251
-
252
- }
253
-
254
- /**
255
- * Validates a license key entered by the user.
256
- *
257
- * @since 6.0.0
258
- *
259
- * @param bool $forced Force to set contextual messages (false by default).
260
- */
261
- public function validate_key( $forced = false, $network = null ) {
262
-
263
- if ( is_null( $network ) ) {
264
- $network = is_network_admin();
265
- }
266
-
267
- $validate = $this->perform_remote_request( 'validate-key', array( 'tgm-updater-key' => $this->key ) );
268
-
269
- // If there was a basic API error in validation, only set the transient for 10 minutes before retrying.
270
- if ( ! $validate ) {
271
- // If forced, set contextual success message.
272
- if ( $forced ) {
273
- $this->errors[] = esc_html__( 'There was an error connecting to the remote key API. Please try again later.', 'google-analytics-for-wordpress' );
274
- }
275
-
276
- return;
277
- }
278
-
279
- $option = $network ? MonsterInsights()->license->get_network_license() : MonsterInsights()->license->get_site_license();
280
- $option['is_expired'] = false;
281
- $option['is_disabled'] = false;
282
- $option['is_invalid'] = false;
283
-
284
- // If a key or author error is returned, the license no longer exists or the user has been deleted, so reset license.
285
- if ( isset( $validate->key ) || isset( $validate->author ) ) {
286
- $option['is_invalid'] = true;
287
- $network ? MonsterInsights()->license->set_network_license( $option ) : MonsterInsights()->license->set_site_license( $option );
288
- $this->errors[] = esc_html__( 'Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
289
-
290
- return;
291
- }
292
-
293
- // If the license has expired, set the transient and expired flag and return.
294
- if ( isset( $validate->expired ) ) {
295
- $option['is_expired'] = true;
296
- $network ? MonsterInsights()->license->set_network_license( $option ) : MonsterInsights()->license->set_site_license( $option );
297
- // Translators: The link to the MonsterInsights website.
298
- $this->errors[] = sprintf( esc_html__( 'Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="' . monsterinsights_get_url( 'admin-notices', 'expired-license', 'https://www.monsterinsights.com/login/' ) . '" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
299
-
300
- return;
301
- }
302
-
303
- // If the license is disabled, set the transient and disabled flag and return.
304
- if ( isset( $validate->disabled ) ) {
305
- $option['is_disabled'] = true;
306
- $network ? MonsterInsights()->license->set_network_license( $option ) : MonsterInsights()->license->set_site_license( $option );
307
- $this->errors[] = esc_html__( 'Your license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
308
-
309
- return;
310
- }
311
-
312
- // If forced, set contextual success message.
313
- if ( ( ! empty( $validate->key ) || ! empty( $this->key ) ) && $forced ) {
314
- $key = ! empty( $validate->key ) ? $validate->key : $this->key;
315
- delete_transient( '_monsterinsights_addons' );
316
- monsterinsights_get_addons_data( $key );
317
- $this->success[] = esc_html__( 'Congratulations! Your key has been refreshed successfully.', 'google-analytics-for-wordpress' );
318
- }
319
-
320
- $option = array();
321
- $option = $network ? MonsterInsights()->license->get_network_license() : MonsterInsights()->license->get_site_license();
322
- $option['type'] = isset( $validate->type ) ? $validate->type : $option['type'];
323
- $option['is_expired'] = false;
324
- $option['is_disabled'] = false;
325
- $option['is_invalid'] = false;
326
- $network ? MonsterInsights()->license->set_network_license( $option ) : MonsterInsights()->license->set_site_license( $option );
327
-
328
- }
329
-
330
- /**
331
- * Maybe deactivates a license key entered by the user.
332
- *
333
- * @since 6.0.0
334
- *
335
- * @return null Return early if the key fails to be deactivated.
336
- */
337
- public function maybe_deactivate_key() {
338
-
339
- if ( empty( $_POST['monsterinsights-license-key'] ) || empty( $_POST['monsterinsights-deactivate-submit'] ) ) {
340
- return;
341
- }
342
-
343
- if ( ! wp_verify_nonce( $_POST['monsterinsights-key-nonce'], 'monsterinsights-key-nonce' ) ) {
344
- return;
345
- }
346
-
347
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
348
- return;
349
- }
350
-
351
- $this->deactivate_key();
352
-
353
- }
354
-
355
- /**
356
- * Deactivate the license key with ajax.
357
- */
358
- public function ajax_deactivate_key() {
359
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
360
-
361
- $network_admin = isset( $_POST['network'] ) && $_POST['network'];
362
-
363
- $license = ! empty( $_POST['license'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['license'] ) ) ) : false;
364
-
365
- if ( ! $license ) {
366
- wp_send_json_error(
367
- array(
368
- 'error' => esc_html__( 'Please refresh the page and try again.', 'google-analytics-for-wordpress' ),
369
- )
370
- );
371
- }
372
-
373
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
374
- wp_send_json_error(
375
- array(
376
- 'error' => esc_html__( 'You are not allowed to deactivate the license key.', 'google-analytics-for-wordpress' ),
377
- )
378
- );
379
- }
380
-
381
- $deactivate = $this->perform_remote_request( 'deactivate-key', array( 'tgm-updater-key' => $license ) );
382
-
383
- if ( ! $deactivate ) {
384
- wp_send_json_error(
385
- array(
386
- 'error' => esc_html__( 'There was an error connecting to the remote key API. Please try again later.', 'google-analytics-for-wordpress' ),
387
- )
388
- );
389
- }
390
-
391
- if ( ! empty( $deactivate->error ) ) {
392
- wp_send_json_error(
393
- array(
394
- 'error' => $deactivate->error,
395
- )
396
- );
397
-
398
- }
399
-
400
- $network_admin ? MonsterInsights()->license->delete_network_license() : MonsterInsights()->license->delete_site_license();
401
-
402
- wp_send_json_success(
403
- array(
404
- 'message' => isset( $deactivate->success ) ? $deactivate->success : esc_html__( 'Congratulations! You have deactivated the key from this site successfully.', 'google-analytics-for-wordpress' ),
405
- )
406
- );
407
- }
408
-
409
- /**
410
- * Deactivates a license key entered by the user.
411
- *
412
- * @since 6.0.0
413
- */
414
- public function deactivate_key() {
415
-
416
- // Perform a request to deactivate the key.
417
- $deactivate = $this->perform_remote_request( 'deactivate-key', array( 'tgm-updater-key' => $_POST['monsterinsights-license-key'] ) );
418
-
419
- // If it returns false, send back a generic error message and return.
420
- if ( ! $deactivate ) {
421
- $this->errors[] = esc_html__( 'There was an error connecting to the remote key API. Please try again later.', 'google-analytics-for-wordpress' );
422
-
423
- return;
424
- }
425
-
426
- // If an error is returned, set the error and return.
427
- if ( ! empty( $deactivate->error ) && ! monsterinsights_is_debug_mode() ) {
428
- $this->errors[] = $deactivate->error;
429
-
430
- return;
431
- }
432
-
433
- // Otherwise, our request has been done successfully. Reset the option and set the success message.
434
- $this->success[] = isset( $deactivate->success ) ? $deactivate->success : esc_html__( 'Congratulations! You have deactivated the key from this site successfully.', 'google-analytics-for-wordpress' );
435
- is_network_admin() ? MonsterInsights()->license->delete_network_license() : MonsterInsights()->license->delete_site_license();
436
-
437
- }
438
-
439
- /**
440
- * Maybe refreshes a license key.
441
- *
442
- * @since 6.0.0
443
- *
444
- * @return null Return early if the key fails to be refreshed.
445
- */
446
- public function maybe_refresh_key() {
447
-
448
- if ( empty( $_POST['monsterinsights-license-key'] ) || empty( $_POST['monsterinsights-refresh-submit'] ) ) {
449
- return;
450
- }
451
-
452
- if ( ! wp_verify_nonce( $_POST['monsterinsights-key-nonce'], 'monsterinsights-key-nonce' ) ) {
453
- return;
454
- }
455
-
456
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
457
- return;
458
- }
459
-
460
- // Refreshing is simply a word alias for validating a key. Force true to set contextual messages.
461
- $this->validate_key( true );
462
-
463
- }
464
-
465
- /**
466
- * Outputs any notices generated by the class.
467
- *
468
- * @since 7.0.0
469
- */
470
- public function monsterinsights_notices() {
471
- if ( ! monsterinsights_is_pro_version() ) {
472
- return;
473
- }
474
-
475
- $screen = get_current_screen();
476
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
477
- return;
478
- }
479
-
480
- if ( ! empty( $this->errors ) ) { ?>
481
- <div class="error">
482
- <p><?php echo implode( '<br>', $this->errors ); ?></p>
483
- </div>
484
- <?php } else if ( ! empty( $this->success ) ) { ?>
485
- <div class="updated">
486
- <p><?php echo implode( '<br>', $this->success ); ?></p>
487
- </div>
488
- <?php }
489
- }
490
-
491
- /**
492
- * Queries the remote URL via wp_remote_post and returns a json decoded response.
493
- *
494
- * @since 6.0.0
495
- *
496
- * @param string $action The name of the $_POST action var.
497
- * @param array $body The content to retrieve from the remote URL.
498
- * @param array $headers The headers to send to the remote URL.
499
- * @param string $return_format The format for returning content from the remote URL.
500
- *
501
- * @return string|bool Json decoded response on success, false on failure.
502
- */
503
- public function perform_remote_request( $action, $body = array(), $headers = array(), $return_format = 'json' ) {
504
-
505
- // Build the body of the request.
506
- $body = wp_parse_args(
507
- $body,
508
- array(
509
- 'tgm-updater-action' => $action,
510
- 'tgm-updater-key' => $this->key,
511
- 'tgm-updater-wp-version' => get_bloginfo( 'version' ),
512
- 'tgm-updater-referer' => site_url(),
513
- 'tgm-updater-mi-version' => MONSTERINSIGHTS_VERSION,
514
- 'tgm-updater-is-pro' => monsterinsights_is_pro_version(),
515
- )
516
- );
517
- $body = http_build_query( $body, '', '&' );
518
-
519
- // Build the headers of the request.
520
- $headers = wp_parse_args(
521
- $headers,
522
- array(
523
- 'Content-Type' => 'application/x-www-form-urlencoded',
524
- 'Content-Length' => strlen( $body )
525
- )
526
- );
527
-
528
- // Setup variable for wp_remote_post.
529
- $post = array(
530
- 'headers' => $headers,
531
- 'body' => $body
532
- );
533
-
534
- // Perform the query and retrieve the response.
535
- $response = wp_remote_post( monsterinsights_get_licensing_url(), $post );
536
- $response_code = wp_remote_retrieve_response_code( $response );
537
- $response_body = wp_remote_retrieve_body( $response );
538
-
539
- // Bail out early if there are any errors.
540
- if ( 200 != $response_code || is_wp_error( $response_body ) ) {
541
- return false;
542
- }
543
-
544
- // Return the json decoded content.
545
- return json_decode( $response_body );
546
- }
547
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/licensing/skin.php CHANGED
@@ -1,104 +1,115 @@
1
- <?php
2
- /**
3
- * Skin class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Upgrader Skin
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- class MonsterInsights_Skin extends WP_Upgrader_Skin {
18
-
19
- /**
20
- * Primary class constructor.
21
- *
22
- * @since 6.0.0
23
- *
24
- * @param array $args Empty array of args (we will use defaults).
25
- */
26
- public function __construct( $args = array() ) {
27
-
28
- parent::__construct();
29
-
30
- }
31
-
32
- /**
33
- * Set the upgrader object and store it as a property in the parent class.
34
- *
35
- * @since 6.0.0
36
- *
37
- * @param object $upgrader The upgrader object (passed by reference).
38
- */
39
- public function set_upgrader( &$upgrader ) {
40
-
41
- if ( is_object( $upgrader ) ) {
42
- $this->upgrader =& $upgrader;
43
- }
44
-
45
- }
46
-
47
- /**
48
- * Set the upgrader result and store it as a property in the parent class.
49
- *
50
- * @since 6.0.0
51
- *
52
- * @param object $result The result of the install process.
53
- */
54
- public function set_result( $result ) {
55
-
56
- $this->result = $result;
57
-
58
- }
59
-
60
- /**
61
- * Empty out the header of its HTML content and only check to see if it has
62
- * been performed or not.
63
- *
64
- * @since 6.0.0
65
- */
66
- public function header() {}
67
-
68
- /**
69
- * Empty out the footer of its HTML contents.
70
- *
71
- * @since 6.0.0
72
- */
73
- function footer() {}
74
-
75
- /**
76
- * Instead of outputting HTML for errors, json_encode the errors and send them
77
- * back to the Ajax script for processing.
78
- *
79
- * @since 6.0.0
80
- *
81
- * @param array $errors Array of errors with the install process.
82
- */
83
- function error( $errors ) {
84
-
85
- if ( ! empty( $errors ) ) {
86
- echo json_encode( array( 'error' => esc_html__( 'There was an error installing the addon. Please try again.', 'google-analytics-for-wordpress' ) ) );
87
- die;
88
- }
89
-
90
- }
91
-
92
- /**
93
- * Empty out the feedback method to prevent outputting HTML strings as the install
94
- * is progressing.
95
- *
96
- * @since 6.0.0
97
- *
98
- * @param string $string The feedback string.
99
- */
100
- function feedback( $string ) {
101
-
102
- }
103
-
104
- }
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Skin class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Upgrader Skin
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ class MonsterInsights_Skin extends WP_Upgrader_Skin {
18
+
19
+ /**
20
+ * Primary class constructor.
21
+ *
22
+ * @since 6.0.0
23
+ *
24
+ * @param array $args Empty array of args (we will use defaults).
25
+ */
26
+ public function __construct( $args = array() ) {
27
+
28
+ parent::__construct();
29
+
30
+ }
31
+
32
+ /**
33
+ * Set the upgrader object and store it as a property in the parent class.
34
+ *
35
+ * @since 6.0.0
36
+ *
37
+ * @param object $upgrader The upgrader object (passed by reference).
38
+ */
39
+ public function set_upgrader( &$upgrader ) {
40
+
41
+ if ( is_object( $upgrader ) ) {
42
+ $this->upgrader =& $upgrader;
43
+ }
44
+
45
+ }
46
+
47
+ /**
48
+ * Set the upgrader result and store it as a property in the parent class.
49
+ *
50
+ * @since 6.0.0
51
+ *
52
+ * @param object $result The result of the install process.
53
+ */
54
+ public function set_result( $result ) {
55
+
56
+ $this->result = $result;
57
+
58
+ }
59
+
60
+ /**
61
+ * Empty out the header of its HTML content and only check to see if it has
62
+ * been performed or not.
63
+ *
64
+ * @since 6.0.0
65
+ */
66
+ public function header() {}
67
+
68
+ /**
69
+ * Empty out the footer of its HTML contents.
70
+ *
71
+ * @since 6.0.0
72
+ */
73
+ function footer() {}
74
+
75
+ /**
76
+ * Instead of outputting HTML for errors, json_encode the errors and send them
77
+ * back to the Ajax script for processing.
78
+ *
79
+ * @since 6.0.0
80
+ *
81
+ * @param array $errors Array of errors with the install process.
82
+ */
83
+ function error( $errors ) {
84
+
85
+ if ( ! empty( $errors ) ) {
86
+ $error_message = esc_html__( 'There was an error installing the addon. Please try again.', 'google-analytics-for-wordpress' );
87
+ if ( is_wp_error( $errors ) ) {
88
+ /**
89
+ * @var WP_Error $errors
90
+ */
91
+ $message = $errors->get_error_message();
92
+
93
+ if ( ! empty( $message ) ) {
94
+ $error_message = sprintf( esc_html__( 'There was an error installing the addon: %s', 'google-analytics-for-wordpress' ), esc_html( $message ) );
95
+ }
96
+ }
97
+
98
+ wp_send_json( array( 'error' => $error_message ) );
99
+ }
100
+
101
+ }
102
+
103
+ /**
104
+ * Empty out the feedback method to prevent outputting HTML strings as the install
105
+ * is progressing.
106
+ *
107
+ * @since 6.0.0
108
+ *
109
+ * @param string $string The feedback string.
110
+ */
111
+ function feedback( $string ) {
112
+
113
+ }
114
+
115
+ }
includes/admin/licensing/updater.php DELETED
@@ -1,383 +0,0 @@
1
- <?php
2
- /**
3
- * Updater class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Updater
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- class MonsterInsights_Updater {
18
-
19
- /**
20
- * Plugin name.
21
- *
22
- * @since 6.0.0
23
- *
24
- * @var bool|string
25
- */
26
- public $plugin_name = false;
27
-
28
- /**
29
- * Plugin slug.
30
- *
31
- * @since 6.0.0
32
- *
33
- * @var bool|string
34
- */
35
- public $plugin_slug = false;
36
-
37
- /**
38
- * Plugin path.
39
- *
40
- * @since 6.0.0
41
- *
42
- * @var bool|string
43
- */
44
- public $plugin_path = false;
45
-
46
- /**
47
- * URL of the plugin.
48
- *
49
- * @since 6.0.0
50
- *
51
- * @var bool|string
52
- */
53
- public $plugin_url = false;
54
-
55
- /**
56
- * Remote URL for getting plugin updates.
57
- *
58
- * @since 6.0.0
59
- *
60
- * @var bool|string
61
- */
62
- public $remote_url = false;
63
-
64
- /**
65
- * Version number of the plugin.
66
- *
67
- * @since 6.0.0
68
- *
69
- * @var bool|int
70
- */
71
- public $version = false;
72
-
73
- /**
74
- * License key for the plugin.
75
- *
76
- * @since 6.0.0
77
- *
78
- * @var bool|string
79
- */
80
- public $key = false;
81
-
82
- /**
83
- * Holds the update data returned from the API.
84
- *
85
- * @since 6.0.0
86
- *
87
- * @var bool|object
88
- */
89
- public $update = false;
90
-
91
- /**
92
- * Holds the plugin info details for the update.
93
- *
94
- * @since 6.0.0
95
- *
96
- * @var bool|object
97
- */
98
- public $info = false;
99
-
100
- /**
101
- * Primary class constructor.
102
- *
103
- * @since 6.0.0
104
- *
105
- * @param array $config Array of updater config args.
106
- */
107
- public function __construct( array $config ) {
108
- // Set class properties.
109
- $accepted_args = array(
110
- 'plugin_name',
111
- 'plugin_slug',
112
- 'plugin_path',
113
- 'plugin_url',
114
- 'remote_url',
115
- 'version',
116
- 'key'
117
- );
118
- foreach ( $accepted_args as $arg ) {
119
- $this->$arg = $config[$arg];
120
- }
121
-
122
- // If the user cannot update plugins, stop processing here.
123
- if ( ! current_user_can( 'update_plugins' ) && ( ! defined( 'DOING_CRON' ) || ! DOING_CRON ) ) {
124
- return;
125
- }
126
-
127
- // If it's our site, then return so we don't redirect loop.
128
- if ( strpos( site_url(), 'monsterinsights.com' ) !== false ) {
129
- return;
130
- }
131
-
132
- // Load the updater hooks and filters.
133
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'update_plugins_filter' ) );
134
-
135
- add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
136
- add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 );
137
-
138
- // ManageWP premium update filters
139
- //add_filter( 'mwp_premium_update_notification', array( $this, 'premium_update_push' ) );
140
- //add_filter( 'mwp_premium_perform_update', array( $this, 'premium_update' ) );
141
-
142
- // Add additional info if the license is expired.
143
- add_action( 'in_plugin_update_message-'. $this->plugin_path, array( $this, 'maybe_show_license_expired_message' ), 10, 2 );
144
- }
145
-
146
- public function maybe_show_license_expired_message( $plugin_data, $response ) {
147
- // If there's no download link but there is an update available there's an issue with the license.
148
- if ( empty( $response->package ) ) {
149
- $settings_url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
150
- // Translators: First one is a link to the settings page, second one is closing tag, third is a link to MonsterInsights.com
151
- echo '<br />' . sprintf( __( 'In order to enable updates, you need to have a valid license key on the %1$ssettings page%2$s. If your license key is expired or you need a new key, then %3$sclick here to purchase MonsterInsights Pro%2$s.', 'google-analytics-for-wordpress' ), '<a href="' . esc_url( $settings_url ) . '">', '</a>', '<a href="' . monsterinsights_get_url( 'Plugin update', $this->plugin_name ) . '">' );
152
- }
153
- }
154
-
155
- /**
156
- * Infuse plugin update details when WordPress runs its update checker.
157
- *
158
- * @since 6.0.0
159
- *
160
- * @param object $value The WordPress update object.
161
- * @return object $value Amended WordPress update object on success, default if object is empty.
162
- */
163
- public function update_plugins_filter( $value ) {
164
-
165
- // If no update object exists, return early.
166
- if ( empty( $value ) ) {
167
- return $value;
168
- }
169
-
170
- // Run update check by pinging the external API. If it fails, return the default update object.
171
- if ( ! $this->update ) {
172
- $this->update = $this->perform_remote_request( 'get-plugin-update', array( 'tgm-updater-plugin' => $this->plugin_slug ) );
173
- if ( ! $this->update || ! empty( $this->update->error ) ) {
174
- $this->update = false;
175
- return $value;
176
- }
177
- }
178
-
179
- // Infuse the update object with our data if the version from the remote API is newer.
180
- if ( isset( $this->update->new_version ) && version_compare( $this->version, $this->update->new_version, '<' ) ) {
181
- // The $plugin_update object contains new_version, package, slug and last_update keys.
182
- //$this->update->full_slug = $this->plugin_slug;
183
- //$this->update->name = $this->plugin_name;
184
- $this->update->monsterinsights_plugin = true;
185
- $this->update->old_version = $this->version;
186
- $this->update->plugin = $this->plugin_path;
187
- $value->response[$this->plugin_path] = $this->update;
188
- }
189
-
190
- // Return the update object.
191
- return $value;
192
-
193
- }
194
-
195
- /**
196
- * Disables SSL verification to prevent download package failures.
197
- *
198
- * @since 6.0.0
199
- *
200
- * @param array $args Array of request args.
201
- * @param string $url The URL to be pinged.
202
- * @return array $args Amended array of request args.
203
- */
204
- public function http_request_args( $args, $url ) {
205
-
206
- // If this is an SSL request and we are performing an upgrade routine, disable SSL verification.
207
- if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'tgm-updater-action=get-plugin-update' ) ) {
208
- $args['sslverify'] = false;
209
- }
210
-
211
- return $args;
212
-
213
- }
214
-
215
- /**
216
- * Filters the plugins_api function to get our own custom plugin information
217
- * from our private repo.
218
- *
219
- * @since 6.0.0
220
- *
221
- * @param object $api The original plugins_api object.
222
- * @param string $action The action sent by plugins_api.
223
- * @param array $args Additional args to send to plugins_api.
224
- * @return object $api New stdClass with plugin information on success, default response on failure.
225
- */
226
- public function plugins_api( $api, $action = '', $args = null ) {
227
-
228
- $plugin = ( 'plugin_information' == $action ) && isset( $args->slug ) && ( $this->plugin_slug == $args->slug );
229
-
230
- // If our plugin matches the request, set our own plugin data, else return the default response.
231
- if ( $plugin ) {
232
- return $this->set_plugins_api( $api );
233
- } else {
234
- return $api;
235
- }
236
-
237
- }
238
-
239
- /**
240
- * Pings a remote API to retrieve plugin information for WordPress to display.
241
- *
242
- * @since 6.0.0
243
- *
244
- * @param object $default_api The default API object.
245
- * @return object $api Return custom plugin information to plugins_api.
246
- */
247
- public function set_plugins_api( $default_api ) {
248
-
249
- // Perform the remote request to retrieve our plugin information. If it fails, return the default object.
250
- if ( ! $this->info ) {
251
- $this->info = $this->perform_remote_request( 'get-plugin-info', array( 'tgm-updater-plugin' => $this->plugin_slug ) );
252
- if ( ! $this->info || ! empty( $this->info->error ) ) {
253
- $this->info = false;
254
- return $default_api;
255
- }
256
- }
257
-
258
- // Create a new stdClass object and populate it with our plugin information.
259
- $api = new stdClass;
260
- $api->name = isset( $this->info->name ) ? $this->info->name : '';
261
- $api->slug = isset( $this->info->slug ) ? $this->info->slug : '';
262
- $api->version = isset( $this->info->version ) ? $this->info->version : '';
263
- $api->author = isset( $this->info->author ) ? $this->info->author : '';
264
- $api->author_profile = isset( $this->info->author_profile ) ? $this->info->author_profile : '';
265
- $api->requires = isset( $this->info->requires ) ? $this->info->requires : '';
266
- $api->tested = isset( $this->info->tested ) ? $this->info->tested : '';
267
- $api->last_updated = isset( $this->info->last_updated ) ? $this->info->last_updated : '';
268
- $api->homepage = isset( $this->info->homepage ) ? $this->info->homepage : '';
269
-
270
- $changelog = isset( $this->info->changelog ) ? $this->info->changelog : '';
271
- $description = isset( $this->info->description ) ? $this->info->description : '';
272
-
273
- if ( ! empty( $changelog ) ) {
274
- if ( ! empty( $description ) ) {
275
- $api->sections['description'] = $description;
276
- $api->sections['changelog'] = $changelog;
277
- } else {
278
- $api->sections['changelog'] = $changelog;
279
- }
280
- } else if ( ! empty( $description ) ) {
281
- $api->sections['description'] = $description;
282
- } else {
283
- $api->sections = array();
284
- }
285
-
286
- $api->download_link = isset( $this->info->download_link ) ? $this->info->download_link : '';
287
-
288
- // Return the new API object with our custom data.
289
- return $api;
290
-
291
- }
292
-
293
- // Integration with ManageWP
294
- public function premium_update_push( $premium_update ) {
295
- if ( ! function_exists( 'get_plugin_data' ) ) {
296
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
297
- }
298
-
299
- $update = $this->set_plugins_api( array() );
300
- if ( ! empty( $update ) && version_compare( MONSTERINSIGHTS_VERSION, $update->version, '<' ) ) {
301
- $plugin_data = get_plugin_data( $update->slug );
302
- $plugin_data['type'] = 'plugin';
303
- $plugin_data['slug'] = $update->slug;
304
- $plugin_data['new_version'] = $update->version;
305
- $premium_update[] = $plugin_data;
306
- }
307
- return $premium_update;
308
- }
309
-
310
- // Integration with ManageWP
311
- public function premium_update( $premium_update ) {
312
- if ( ! function_exists( 'get_plugin_data' ) ) {
313
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
314
- }
315
-
316
- $update = $this->set_plugins_api( array() );
317
- if ( ! empty( $update ) && version_compare( MONSTERINSIGHTS_VERSION, $update->version, '<' ) ) {
318
- $plugin_data = get_plugin_data( $update->slug );
319
- $plugin_data['type'] = 'plugin';
320
- $plugin_data['slug'] = $update->slug;
321
- $plugin_data['url'] = $update->download_link; // OR provide your own callback function for managing the update
322
- array_push( $premium_update, $plugin_data );
323
- }
324
- return $premium_update;
325
- }
326
-
327
- /**
328
- * Queries the remote URL via wp_remote_post and returns a json decoded response.
329
- *
330
- * @since 6.0.0
331
- *
332
- * @param string $action The name of the $_POST action var.
333
- * @param array $body The content to retrieve from the remote URL.
334
- * @param array $headers The headers to send to the remote URL.
335
- * @param string $return_format The format for returning content from the remote URL.
336
- * @return string|bool Json decoded response on success, false on failure.
337
- */
338
- public function perform_remote_request( $action, $body = array(), $headers = array(), $return_format = 'json' ) {
339
-
340
- // Build the body of the request.
341
- $body = wp_parse_args(
342
- $body,
343
- array(
344
- 'tgm-updater-action' => $action,
345
- 'tgm-updater-key' => $this->key,
346
- 'tgm-updater-wp-version' => get_bloginfo( 'version' ),
347
- 'tgm-updater-referer' => site_url(),
348
- 'tgm-updater-mi-version' => MONSTERINSIGHTS_VERSION,
349
- 'tgm-updater-is-pro' => monsterinsights_is_pro_version(),
350
- )
351
- );
352
- $body = http_build_query( $body, '', '&' );
353
-
354
- // Build the headers of the request.
355
- $headers = wp_parse_args(
356
- $headers,
357
- array(
358
- 'Content-Type' => 'application/x-www-form-urlencoded',
359
- 'Content-Length' => strlen( $body )
360
- )
361
- );
362
-
363
- // Setup variable for wp_remote_post.
364
- $post = array(
365
- 'headers' => $headers,
366
- 'body' => $body
367
- );
368
-
369
- // Perform the query and retrieve the response.
370
- $response = wp_remote_post( esc_url_raw( $this->remote_url ), $post );
371
- $response_code = wp_remote_retrieve_response_code( $response );
372
- $response_body = wp_remote_retrieve_body( $response );
373
-
374
- // Bail out early if there are any errors.
375
- if ( 200 != $response_code || is_wp_error( $response_body ) ) {
376
- return false;
377
- }
378
-
379
- // Return the json decoded content.
380
- return json_decode( $response_body );
381
-
382
- }
383
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/notice.php CHANGED
@@ -1,236 +1,236 @@
1
- <?php
2
- /**
3
- * Notices admin class.
4
- *
5
- * Handles retrieving whether a particular notice has been dismissed or not,
6
- * as well as marking a notice as dismissed.
7
- *
8
- * @since 6.0.0
9
- *
10
- * @package MonsterInsights
11
- * @subpackage Notices
12
- * @author Chris Christoff
13
- */
14
-
15
- // Exit if accessed directly
16
- if ( ! defined( 'ABSPATH' ) ) {
17
- exit;
18
- }
19
-
20
- final class MonsterInsights_Notice_Admin {
21
-
22
- /**
23
- * Holds all dismissed notices
24
- *
25
- * @access public
26
- * @since 6.0.0
27
- * @var array $notices Array of dismissed notices.
28
- */
29
- public $notices;
30
-
31
- /**
32
- * Primary class constructor.
33
- *
34
- * @access public
35
- * @since 6.0.0
36
- */
37
- public function __construct() {
38
-
39
- // Populate $notices
40
- $this->notices = get_option( 'monsterinsights_notices' );
41
- if ( ! is_array( $this->notices ) ) {
42
- $this->notices = array();
43
- }
44
-
45
- }
46
-
47
- /**
48
- * Checks if a given notice has been dismissed or not
49
- *
50
- * @access public
51
- * @since 6.0.0
52
- *
53
- * @param string $notice Programmatic Notice Name
54
- * @return bool Notice Dismissed
55
- */
56
-
57
- public function is_dismissed( $notice ) {
58
- if ( ! isset( $this->notices[ $notice ] ) ) {
59
- return false;
60
- }
61
- return true;
62
-
63
- }
64
-
65
- /**
66
- * Marks the given notice as dismissed
67
- *
68
- * @access public
69
- * @since 6.0.0
70
- *
71
- * @param string $notice Programmatic Notice Name
72
- * @return null
73
- */
74
- public function dismiss( $notice ) {
75
- $this->notices[ $notice ] = true;
76
- update_option( 'monsterinsights_notices', $this->notices );
77
-
78
- }
79
-
80
-
81
- /**
82
- * Marks a notice as not dismissed
83
- *
84
- * @access public
85
- * @since 6.0.0
86
- *
87
- * @param string $notice Programmatic Notice Name
88
- * @return null
89
- */
90
- public function undismiss( $notice ) {
91
- unset( $this->notices[ $notice ] );
92
- update_option( 'monsterinsights_notices', $this->notices );
93
-
94
- }
95
-
96
- /**
97
- * Displays an inline notice with some MonsterInsights styling.
98
- *
99
- * @access public
100
- * @since 6.0.0
101
- *
102
- * @param string $notice Programmatic Notice Name
103
- * @param string $title Title
104
- * @param string $message Message
105
- * @param string $type Message Type (updated|warning|error) - green, yellow/orange and red respectively.
106
- * @param string $button_text Button Text (optional)
107
- * @param string $button_url Button URL (optional)
108
- * @param bool $is_dismissible User can Dismiss Message (default: false)
109
- */
110
- public function display_inline_notice( $name, $title, $message, $type = 'success', $is_dismissible = false, $args = array() ) {
111
- /* Available/Planned $args options
112
- * $args = array(
113
- * 'primary' => array(
114
- * 'text' => '',
115
- * 'url' => '',
116
- * 'target' => '',
117
- * 'class' => 'button button-primary',
118
- * ),
119
- * 'secondary' => array(
120
- * 'text' => '',
121
- * 'url' => '',
122
- * 'target' => '',
123
- * 'class' => 'button button-secondary',
124
- * ),
125
- * 'skip_message_escape' => true // note: This param is for internal use only. Do not use as a developer.
126
- * );
127
- */
128
-
129
-
130
- // Check if the notice is dismissible, and if so has been dismissed.
131
- if ( $is_dismissible && $this->is_dismissed( $name ) ) {
132
- // Nothing to show here, return!
133
- return '';
134
- }
135
-
136
- $dismissible = ( $is_dismissible ) ? ' is-dismissible': '';
137
-
138
- // Display inline notice
139
- ob_start();
140
- ?>
141
- <div class="monsterinsights-notice <?php echo 'monsterinsights-' . esc_attr( $type ) . '-notice' . $dismissible; ?>" data-notice="<?php echo esc_attr( $name ); ?>">
142
- <div class="monsterinsights-notice-icon <?php echo 'monsterinsights-' . esc_attr( $type ) . '-notice-icon'?>">
143
- </div>
144
- <div class="monsterinsights-notice-text <?php echo 'monsterinsights-' . esc_attr( $type ) . '-notice-text'?>">
145
- <?php
146
- // Title
147
- if ( ! empty ( $title ) ) {
148
- ?>
149
- <p class="monsterinsights-notice-title"><?php echo esc_html( $title ); ?></p>
150
- <?php
151
- }
152
-
153
- // Message
154
- if ( ! empty( $message ) ) {
155
- if ( empty( $args['skip_message_escape'] ) ) {
156
- ?>
157
- <p class="monsterinsights-notice-message"><?php echo esc_html( $message ); ?></p>
158
- <?php
159
- } else {
160
- ?>
161
- <p class="monsterinsights-notice-message"><?php echo $message; ?></p>
162
- <?php
163
- }
164
- }
165
-
166
- // Primary Button
167
- if ( ! empty( $args['primary']['text'] ) ) {
168
-
169
- $text = '';
170
- if ( ! empty( $args['primary']['text'] ) ) {
171
- $text = $args['primary']['text'];
172
- }
173
-
174
- $url = '#';
175
- if ( ! empty( $args['primary']['url'] ) ) {
176
- $url = $args['primary']['url'];
177
- }
178
-
179
- $target = '';
180
- if ( ! empty( $args['primary']['target'] ) && $args['primary']['target'] === 'blank') {
181
- $target = ' target="_blank" rel="noopener noreferrer"';
182
- }
183
-
184
- $class = 'button button-primary';
185
- if ( ! empty( $args['primary']['class'] ) ) {
186
- $class = ' class="'. $args['primary']['class'] . '"';
187
- }
188
- ?>
189
- <a href="<?php echo esc_attr( $url ); ?>"<?php echo $target; ?><?php echo $class;?>><?php echo esc_html( $text ); ?></a>
190
- <?php
191
- }
192
-
193
- // Secondary Button
194
- if ( ! empty( $args['secondary']['text'] ) ) {
195
-
196
- $text = '';
197
- if ( ! empty( $args['secondary']['text'] ) ) {
198
- $text = $args['secondary']['text'];
199
- }
200
-
201
- $url = '#';
202
- if ( ! empty( $args['secondary']['url'] ) ) {
203
- $url = $args['secondary']['url'];
204
- }
205
-
206
- $target = '';
207
- if ( ! empty( $args['secondary']['target'] ) && $args['secondary']['target'] === 'blank') {
208
- $target = ' target="_blank" rel="noopener noreferrer"';
209
- }
210
-
211
- $class = 'button button-secondary';
212
- if ( ! empty( $args['secondary']['class'] ) ) {
213
- $class = ' class="'. $args['secondary']['class'] . '"';
214
- }
215
- ?>
216
- <a href="<?php echo esc_attr( $url ); ?>"<?php echo $target; ?><?php echo $class;?>><?php echo esc_html( $text ); ?></a>
217
- <?php
218
- }
219
-
220
- // Dismiss Button
221
- if ( $is_dismissible ) {
222
- ?>
223
- <button type="button" class="notice-dismiss<?php echo $dismissible; ?>">
224
- <span class="screen-reader-text">
225
- <?php esc_html_e( 'Dismiss this notice', 'google-analytics-for-wordpress' ); ?>
226
- </span>
227
- </button>
228
- <?php
229
- }
230
- ?>
231
- </div>
232
- </div>
233
- <?php
234
- return ob_get_clean();
235
- }
236
  }
1
+ <?php
2
+ /**
3
+ * Notices admin class.
4
+ *
5
+ * Handles retrieving whether a particular notice has been dismissed or not,
6
+ * as well as marking a notice as dismissed.
7
+ *
8
+ * @since 6.0.0
9
+ *
10
+ * @package MonsterInsights
11
+ * @subpackage Notices
12
+ * @author Chris Christoff
13
+ */
14
+
15
+ // Exit if accessed directly
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+ final class MonsterInsights_Notice_Admin {
21
+
22
+ /**
23
+ * Holds all dismissed notices
24
+ *
25
+ * @access public
26
+ * @since 6.0.0
27
+ * @var array $notices Array of dismissed notices.
28
+ */
29
+ public $notices;
30
+
31
+ /**
32
+ * Primary class constructor.
33
+ *
34
+ * @access public
35
+ * @since 6.0.0
36
+ */
37
+ public function __construct() {
38
+
39
+ // Populate $notices
40
+ $this->notices = get_option( 'monsterinsights_notices' );
41
+ if ( ! is_array( $this->notices ) ) {
42
+ $this->notices = array();
43
+ }
44
+
45
+ }
46
+
47
+ /**
48
+ * Checks if a given notice has been dismissed or not
49
+ *
50
+ * @access public
51
+ * @since 6.0.0
52
+ *
53
+ * @param string $notice Programmatic Notice Name
54
+ * @return bool Notice Dismissed
55
+ */
56
+
57
+ public function is_dismissed( $notice ) {
58
+ if ( ! isset( $this->notices[ $notice ] ) ) {
59
+ return false;
60
+ }
61
+ return true;
62
+
63
+ }
64
+
65
+ /**
66
+ * Marks the given notice as dismissed
67
+ *
68
+ * @access public
69
+ * @since 6.0.0
70
+ *
71
+ * @param string $notice Programmatic Notice Name
72
+ * @return null
73
+ */
74
+ public function dismiss( $notice ) {
75
+ $this->notices[ $notice ] = true;
76
+ update_option( 'monsterinsights_notices', $this->notices );
77
+
78
+ }
79
+
80
+
81
+ /**
82
+ * Marks a notice as not dismissed
83
+ *
84
+ * @access public
85
+ * @since 6.0.0
86
+ *
87
+ * @param string $notice Programmatic Notice Name
88
+ * @return null
89
+ */
90
+ public function undismiss( $notice ) {
91
+ unset( $this->notices[ $notice ] );
92
+ update_option( 'monsterinsights_notices', $this->notices );
93
+
94
+ }
95
+
96
+ /**
97
+ * Displays an inline notice with some MonsterInsights styling.
98
+ *
99
+ * @access public
100
+ * @since 6.0.0
101
+ *
102
+ * @param string $notice Programmatic Notice Name
103
+ * @param string $title Title
104
+ * @param string $message Message
105
+ * @param string $type Message Type (updated|warning|error) - green, yellow/orange and red respectively.
106
+ * @param string $button_text Button Text (optional)
107
+ * @param string $button_url Button URL (optional)
108
+ * @param bool $is_dismissible User can Dismiss Message (default: false)
109
+ */
110
+ public function display_inline_notice( $name, $title, $message, $type = 'success', $is_dismissible = false, $args = array() ) {
111
+ /* Available/Planned $args options
112
+ * $args = array(
113
+ * 'primary' => array(
114
+ * 'text' => '',
115
+ * 'url' => '',
116
+ * 'target' => '',
117
+ * 'class' => 'button button-primary',
118
+ * ),
119
+ * 'secondary' => array(
120
+ * 'text' => '',
121
+ * 'url' => '',
122
+ * 'target' => '',
123
+ * 'class' => 'button button-secondary',
124
+ * ),
125
+ * 'skip_message_escape' => true // note: This param is for internal use only. Do not use as a developer.
126
+ * );
127
+ */
128
+
129
+
130
+ // Check if the notice is dismissible, and if so has been dismissed.
131
+ if ( $is_dismissible && $this->is_dismissed( $name ) ) {
132
+ // Nothing to show here, return!
133
+ return '';
134
+ }
135
+
136
+ $dismissible = ( $is_dismissible ) ? ' is-dismissible': '';
137
+
138
+ // Display inline notice
139
+ ob_start();
140
+ ?>
141
+ <div class="monsterinsights-notice <?php echo 'monsterinsights-' . esc_attr( $type ) . '-notice' . $dismissible; ?>" data-notice="<?php echo esc_attr( $name ); ?>">
142
+ <div class="monsterinsights-notice-icon <?php echo 'monsterinsights-' . esc_attr( $type ) . '-notice-icon'?>">
143
+ </div>
144
+ <div class="monsterinsights-notice-text <?php echo 'monsterinsights-' . esc_attr( $type ) . '-notice-text'?>">
145
+ <?php
146
+ // Title
147
+ if ( ! empty ( $title ) ) {
148
+ ?>
149
+ <p class="monsterinsights-notice-title"><?php echo esc_html( $title ); ?></p>
150
+ <?php
151
+ }
152
+
153
+ // Message
154
+ if ( ! empty( $message ) ) {
155
+ if ( empty( $args['skip_message_escape'] ) ) {
156
+ ?>
157
+ <p class="monsterinsights-notice-message"><?php echo esc_html( $message ); ?></p>
158
+ <?php
159
+ } else {
160
+ ?>
161
+ <p class="monsterinsights-notice-message"><?php echo $message; ?></p>
162
+ <?php
163
+ }
164
+ }
165
+
166
+ // Primary Button
167
+ if ( ! empty( $args['primary']['text'] ) ) {
168
+
169
+ $text = '';
170
+ if ( ! empty( $args['primary']['text'] ) ) {
171
+ $text = $args['primary']['text'];
172
+ }
173
+
174
+ $url = '#';
175
+ if ( ! empty( $args['primary']['url'] ) ) {
176
+ $url = $args['primary']['url'];
177
+ }
178
+
179
+ $target = '';
180
+ if ( ! empty( $args['primary']['target'] ) && $args['primary']['target'] === 'blank') {
181
+ $target = ' target="_blank" rel="noopener noreferrer"';
182
+ }
183
+
184
+ $class = 'button button-primary';
185
+ if ( ! empty( $args['primary']['class'] ) ) {
186
+ $class = ' class="'. $args['primary']['class'] . '"';
187
+ }
188
+ ?>
189
+ <a href="<?php echo esc_attr( $url ); ?>"<?php echo $target; ?><?php echo $class;?>><?php echo esc_html( $text ); ?></a>
190
+ <?php
191
+ }
192
+
193
+ // Secondary Button
194
+ if ( ! empty( $args['secondary']['text'] ) ) {
195
+
196
+ $text = '';
197
+ if ( ! empty( $args['secondary']['text'] ) ) {
198
+ $text = $args['secondary']['text'];
199
+ }
200
+
201
+ $url = '#';
202
+ if ( ! empty( $args['secondary']['url'] ) ) {
203
+ $url = $args['secondary']['url'];
204
+ }
205
+
206
+ $target = '';
207
+ if ( ! empty( $args['secondary']['target'] ) && $args['secondary']['target'] === 'blank') {
208
+ $target = ' target="_blank" rel="noopener noreferrer"';
209
+ }
210
+
211
+ $class = 'button button-secondary';
212
+ if ( ! empty( $args['secondary']['class'] ) ) {
213
+ $class = ' class="'. $args['secondary']['class'] . '"';
214
+ }
215
+ ?>
216
+ <a href="<?php echo esc_attr( $url ); ?>"<?php echo $target; ?><?php echo $class;?>><?php echo esc_html( $text ); ?></a>
217
+ <?php
218
+ }
219
+
220
+ // Dismiss Button
221
+ if ( $is_dismissible ) {
222
+ ?>
223
+ <button type="button" class="notice-dismiss<?php echo $dismissible; ?>">
224
+ <span class="screen-reader-text">
225
+ <?php esc_html_e( 'Dismiss this notice', 'google-analytics-for-wordpress' ); ?>
226
+ </span>
227
+ </button>
228
+ <?php
229
+ }
230
+ ?>
231
+ </div>
232
+ </div>
233
+ <?php
234
+ return ob_get_clean();
235
+ }
236
  }
includes/admin/pages/addons.php CHANGED
@@ -1,138 +1,183 @@
1
- <?php
2
- /**
3
- * Addons class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
-
17
- /**
18
- * Callback to output the MonsterInsights addons page.
19
- *
20
- * @since 6.0.0
21
- */
22
- function monsterinsights_addons_page() {
23
- echo monsterinsights_ublock_notice();
24
- monsterinsights_settings_error_page( 'monsterinsights-addons' );
25
- monsterinsights_settings_inline_js();
26
- }
27
-
28
- /**
29
- * Retrieves addons from the stored transient or remote server.
30
- *
31
- * @since 6.0.0
32
- *
33
- * @return bool | array false | Array of licensed and unlicensed Addons.
34
- */
35
- function monsterinsights_get_addons() {
36
-
37
- // Get license key and type.
38
- $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
39
- $type = is_network_admin() ? MonsterInsights()->license->get_network_license_type() : MonsterInsights()->license->get_site_license_type();
40
-
41
- // Get addons data from transient or perform API query if no transient.
42
- if ( false === ( $addons = get_transient( '_monsterinsights_addons' ) ) ) {
43
- $addons = monsterinsights_get_addons_data( $key );
44
- }
45
-
46
- // If no Addons exist, return false
47
- if ( ! $addons ) {
48
- return false;
49
- }
50
-
51
- // Iterate through Addons, to build two arrays:
52
- // - Addons the user is licensed to use,
53
- // - Addons the user isn't licensed to use.
54
- $results = array(
55
- 'licensed' => array(),
56
- 'unlicensed'=> array(),
57
- );
58
- foreach ( (array) $addons as $i => $addon ) {
59
-
60
- // Determine whether the user is licensed to use this Addon or not.
61
- if (
62
- empty( $type ) ||
63
- ( in_array( 'Pro', $addon->categories ) && ( $type != 'pro' && $type != 'master' ) ) ||
64
- ( in_array( 'Plus', $addon->categories ) && $type != 'plus' && $type != 'pro' && $type != 'master' ) ||
65
- ( in_array( 'Basic', $addon->categories ) && ( $type != 'basic' && $type != 'plus' && $type != 'pro' && $type != 'master' ) )
66
- ) {
67
- // Unlicensed
68
- $results['unlicensed'][] = $addon;
69
- continue;
70
- }
71
-
72
- // Licensed
73
- $results['licensed'][] = $addon;
74
-
75
- }
76
-
77
- // Return Addons, split by licensed and unlicensed.
78
- return $results;
79
-
80
- }
81
-
82
- /**
83
- * Pings the remote server for addons data.
84
- *
85
- * @since 6.0.0
86
- *
87
- * @param string $key The user license key.
88
- * @return array Array of addon data otherwise.
89
- */
90
- function monsterinsights_get_addons_data( $key ) {
91
- $type = is_network_admin() ? MonsterInsights()->license->get_network_license_type() : MonsterInsights()->license->get_site_license_type();
92
-
93
- // Get Addons
94
- // If the key is valid, we'll get personalised upgrade URLs for each Addon (if necessary) and plugin update information.
95
- if ( $key ) {
96
- $addons = MonsterInsights()->license_actions->perform_remote_request( 'get-addons-data-v600', array( 'tgm-updater-key' => $key ) );
97
- } else {
98
- $addons = MonsterInsights()->license_actions->perform_remote_request( 'get-all-addons-data', array() );
99
- }
100
-
101
- // If there was an API error, set transient for only 10 minutes.
102
- if ( ! $addons ) {
103
- set_transient( '_monsterinsights_addons', false, 10 * MINUTE_IN_SECONDS );
104
- return false;
105
- }
106
-
107
- // If there was an error retrieving the addons, set the error.
108
- if ( isset( $addons->error ) ) {
109
- set_transient( '_monsterinsights_addons', false, 10 * MINUTE_IN_SECONDS );
110
- return false;
111
- }
112
-
113
- // Otherwise, our request worked. Save the data and return it.
114
- set_transient( '_monsterinsights_addons', $addons, 4 * HOUR_IN_SECONDS );
115
- return $addons;
116
-
117
- }
118
-
119
- /**
120
- * Retrieve the plugin basename from the plugin slug.
121
- *
122
- * @since 6.0.0
123
- *
124
- * @param string $slug The plugin slug.
125
- * @return string The plugin basename if found, else the plugin slug.
126
- */
127
- function monsterinsights_get_plugin_basename_from_slug( $slug ) {
128
- $keys = array_keys( get_plugins() );
129
-
130
- foreach ( $keys as $key ) {
131
- if ( preg_match( '|^' . $slug . '|', $key ) ) {
132
- return $key;
133
- }
134
- }
135
-
136
- return $slug;
137
-
138
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Addons class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+
17
+ /**
18
+ * Callback to output the MonsterInsights addons page.
19
+ *
20
+ * @since 6.0.0
21
+ */
22
+ function monsterinsights_addons_page() {
23
+ echo monsterinsights_ublock_notice();
24
+ monsterinsights_settings_error_page( 'monsterinsights-addons' );
25
+ monsterinsights_settings_inline_js();
26
+ }
27
+
28
+ /**
29
+ * Retrieves addons from the stored transient or remote server.
30
+ *
31
+ * @since 6.0.0
32
+ *
33
+ * @return bool | array false | Array of licensed and unlicensed Addons.
34
+ */
35
+ function monsterinsights_get_addons() {
36
+
37
+ // Get license key and type.
38
+ $key = '';
39
+ $type = 'lite';
40
+ if ( monsterinsights_is_pro_version() ) {
41
+ $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
42
+ $type = is_network_admin() ? MonsterInsights()->license->get_network_license_type() : MonsterInsights()->license->get_site_license_type();
43
+ }
44
+
45
+ // Get addons data from transient or perform API query if no transient.
46
+ if ( false === ( $addons = get_transient( '_monsterinsights_addons' ) ) ) {
47
+ $addons = monsterinsights_get_addons_data( $key );
48
+ }
49
+
50
+ // If no Addons exist, return false
51
+ if ( ! $addons ) {
52
+ return false;
53
+ }
54
+
55
+ // Iterate through Addons, to build two arrays:
56
+ // - Addons the user is licensed to use,
57
+ // - Addons the user isn't licensed to use.
58
+ $results = array(
59
+ 'licensed' => array(),
60
+ 'unlicensed'=> array(),
61
+ );
62
+ foreach ( (array) $addons as $i => $addon ) {
63
+
64
+ // Determine whether the user is licensed to use this Addon or not.
65
+ if (
66
+ empty( $type ) ||
67
+ ( in_array( 'Pro', $addon->categories ) && ( $type != 'pro' && $type != 'master' ) ) ||
68
+ ( in_array( 'Plus', $addon->categories ) && $type != 'plus' && $type != 'pro' && $type != 'master' ) ||
69
+ ( in_array( 'Basic', $addon->categories ) && ( $type != 'basic' && $type != 'plus' && $type != 'pro' && $type != 'master' ) )
70
+ ) {
71
+ // Unlicensed
72
+ $results['unlicensed'][] = $addon;
73
+ continue;
74
+ }
75
+
76
+ // Licensed
77
+ $results['licensed'][] = $addon;
78
+
79
+ }
80
+
81
+ // Return Addons, split by licensed and unlicensed.
82
+ return $results;
83
+
84
+ }
85
+
86
+ /**
87
+ * Pings the remote server for addons data.
88
+ *
89
+ * @since 6.0.0
90
+ *
91
+ * @param string $key The user license key.
92
+ * @return array Array of addon data otherwise.
93
+ */
94
+ function monsterinsights_get_addons_data( $key ) {
95
+ // Get Addons
96
+ // If the key is valid, we'll get personalised upgrade URLs for each Addon (if necessary) and plugin update information.
97
+ if ( monsterinsights_is_pro_version() && $key ) {
98
+ $addons = MonsterInsights()->license_actions->perform_remote_request( 'get-addons-data-v600', array( 'tgm-updater-key' => $key ) );
99
+ } else {
100
+ $addons = monsterinsights_get_all_addons_data();
101
+ }
102
+
103
+ // If there was an API error, set transient for only 10 minutes.
104
+ if ( ! $addons ) {
105
+ set_transient( '_monsterinsights_addons', false, 10 * MINUTE_IN_SECONDS );
106
+ return false;
107
+ }
108
+
109
+ // If there was an error retrieving the addons, set the error.
110
+ if ( isset( $addons->error ) ) {
111
+ set_transient( '_monsterinsights_addons', false, 10 * MINUTE_IN_SECONDS );
112
+ return false;
113
+ }
114
+
115
+ // Otherwise, our request worked. Save the data and return it.
116
+ set_transient( '_monsterinsights_addons', $addons, 4 * HOUR_IN_SECONDS );
117
+ return $addons;
118
+
119
+ }
120
+
121
+ /**
122
+ * Get all addons without a license, for lite users.
123
+ *
124
+ * @return array|bool|mixed|object
125
+ */
126
+ function monsterinsights_get_all_addons_data() {
127
+ // Build the body of the request.
128
+ $body = array(
129
+ 'tgm-updater-action' => 'get-all-addons-data',
130
+ 'tgm-updater-key' => '',
131
+ 'tgm-updater-wp-version' => get_bloginfo( 'version' ),
132
+ 'tgm-updater-referer' => site_url(),
133
+ 'tgm-updater-mi-version' => MONSTERINSIGHTS_VERSION,
134
+ 'tgm-updater-is-pro' => false,
135
+ );
136
+ $body = http_build_query( $body, '', '&' );
137
+
138
+ // Build the headers of the request.
139
+ $headers = array(
140
+ 'Content-Type' => 'application/x-www-form-urlencoded',
141
+ 'Content-Length' => strlen( $body ),
142
+ );
143
+
144
+ // Setup variable for wp_remote_post.
145
+ $post = array(
146
+ 'headers' => $headers,
147
+ 'body' => $body,
148
+ );
149
+
150
+ // Perform the query and retrieve the response.
151
+ $response = wp_remote_post( monsterinsights_get_licensing_url(), $post );
152
+ $response_code = wp_remote_retrieve_response_code( $response );
153
+ $response_body = wp_remote_retrieve_body( $response );
154
+
155
+ // Bail out early if there are any errors.
156
+ if ( 200 !== $response_code || is_wp_error( $response_body ) ) {
157
+ return false;
158
+ }
159
+
160
+ // Return the json decoded content.
161
+ return json_decode( $response_body );
162
+ }
163
+
164
+ /**
165
+ * Retrieve the plugin basename from the plugin slug.
166
+ *
167
+ * @since 6.0.0
168
+ *
169
+ * @param string $slug The plugin slug.
170
+ * @return string The plugin basename if found, else the plugin slug.
171
+ */
172
+ function monsterinsights_get_plugin_basename_from_slug( $slug ) {
173
+ $keys = array_keys( get_plugins() );
174
+
175
+ foreach ( $keys as $key ) {
176
+ if ( preg_match( '|^' . $slug . '|', $key ) ) {
177
+ return $key;
178
+ }
179
+ }
180
+
181
+ return $slug;
182
+
183
+ }
includes/admin/pages/reports.php CHANGED
@@ -1,64 +1,65 @@
1
- <?php
2
- /**
3
- * Reports class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Reports
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- function monsterinsights_reports_page_body_class( $classes ) {
18
- if ( ! empty( $_REQUEST['page'] ) && $_REQUEST['page'] === 'monsterinsights_reports' ) {
19
- $classes .= ' monsterinsights-reporting-page ';
20
- }
21
- return $classes;
22
- }
23
- add_filter( 'admin_body_class', 'monsterinsights_reports_page_body_class' );
24
-
25
- /**
26
- * Callback for getting all of the reports tabs for MonsterInsights.
27
- *
28
- * @since 6.0.0
29
- * @access public
30
- *
31
- * @return array Array of tab information.
32
- */
33
- function monsterinsights_get_reports() {
34
- /**
35
- * Developer Alert:
36
- *
37
- * Per the README, this is considered an internal hook and should
38
- * not be used by other developers. This hook's behavior may be modified
39
- * or the hook may be removed at any time, without warning.
40
- */
41
- $reports = apply_filters( 'monsterinsights_get_reports', array() );
42
- return $reports;
43
- }
44
-
45
- /**
46
- * Callback to output the MonsterInsights reports page.
47
- *
48
- * @since 6.0.0
49
- * @access public
50
- *
51
- * @return void
52
- */
53
- function monsterinsights_reports_page() {
54
- /**
55
- * Developer Alert:
56
- *
57
- * Per the README, this is considered an internal hook and should
58
- * not be used by other developers. This hook's behavior may be modified
59
- * or the hook may be removed at any time, without warning.
60
- */
61
- do_action( 'monsterinsights_head' );
62
- echo monsterinsights_ublock_notice();
63
- monsterinsights_settings_error_page( 'monsterinsights-reports');
64
- }
 
1
+ <?php
2
+ /**
3
+ * Reports class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Reports
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ function monsterinsights_reports_page_body_class( $classes ) {
18
+ if ( ! empty( $_REQUEST['page'] ) && $_REQUEST['page'] === 'monsterinsights_reports' ) {
19
+ $classes .= ' monsterinsights-reporting-page ';
20
+ }
21
+ return $classes;
22
+ }
23
+ add_filter( 'admin_body_class', 'monsterinsights_reports_page_body_class' );
24
+
25
+ /**
26
+ * Callback for getting all of the reports tabs for MonsterInsights.
27
+ *
28
+ * @since 6.0.0
29
+ * @access public
30
+ *
31
+ * @return array Array of tab information.
32
+ */
33
+ function monsterinsights_get_reports() {
34
+ /**
35
+ * Developer Alert:
36
+ *
37
+ * Per the README, this is considered an internal hook and should
38
+ * not be used by other developers. This hook's behavior may be modified
39
+ * or the hook may be removed at any time, without warning.
40
+ */
41
+ $reports = apply_filters( 'monsterinsights_get_reports', array() );
42
+ return $reports;
43
+ }
44
+
45
+ /**
46
+ * Callback to output the MonsterInsights reports page.
47
+ *
48
+ * @since 6.0.0
49
+ * @access public
50
+ *
51
+ * @return void
52
+ */
53
+ function monsterinsights_reports_page() {
54
+ /**
55
+ * Developer Alert:
56
+ *
57
+ * Per the README, this is considered an internal hook and should
58
+ * not be used by other developers. This hook's behavior may be modified
59
+ * or the hook may be removed at any time, without warning.
60
+ */
61
+ do_action( 'monsterinsights_head' );
62
+ echo monsterinsights_ublock_notice();
63
+ monsterinsights_settings_error_page( 'monsterinsights-reports');
64
+ monsterinsights_settings_inline_js();
65
+ }
includes/admin/pages/settings.php CHANGED
@@ -1,123 +1,124 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
7
- /**
8
- * Callback to output the MonsterInsights settings page.
9
- *
10
- * @since 7.4.0
11
- * @access public
12
- *
13
- * @return void
14
- */
15
- function monsterinsights_settings_page() {
16
- echo monsterinsights_ublock_notice();
17
- monsterinsights_settings_error_page( 'monsterinsights-vue-site-settings' );
18
- monsterinsights_settings_inline_js();
19
- }
20
-
21
- function monsterinsights_network_page() {
22
- echo monsterinsights_ublock_notice();
23
- monsterinsights_settings_error_page( 'monsterinsights-vue-network-settings' );
24
- monsterinsights_settings_inline_js();
25
- }
26
-
27
- /**
28
- * Attempt to catch the js error preventing the Vue app from loading and displaying that message for better support.
29
- */
30
- function monsterinsights_settings_inline_js() {
31
- ?>
32
- <script type="text/javascript">
33
- var ua = window.navigator.userAgent;
34
- var msie = ua.indexOf( 'MSIE ' );
35
- if ( msie > 0 ) {
36
- var browser_error = document.getElementById( 'monsterinsights-error-browser' );
37
- var js_error = document.getElementById( 'monsterinsights-error-js' );
38
- js_error.style.display = 'none';
39
- browser_error.style.display = 'block';
40
- } else {
41
- window.onerror = function myErrorHandler( errorMsg, url, lineNumber ) {
42
- /* Don't try to put error in container that no longer exists post-vue loading */
43
- var message_container = document.getElementById( 'monsterinsights-nojs-error-message' );
44
- if ( ! message_container ) {
45
- return false;
46
- }
47
- var message = document.getElementById( 'monsterinsights-alert-message' );
48
- message.innerHTML = errorMsg;
49
- message_container.style.display = 'block';
50
- return false;
51
- }
52
- }
53
- </script>
54
- <?php
55
- }
56
-
57
-
58
- /**
59
- * Error page HTML
60
- **/
61
- function monsterinsights_settings_error_page( $id = 'monsterinsights-vue-site-settings', $footer = '', $margin = '82px 0' ) {
62
- $inline_logo_image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAd4AAABaCAYAAAAWyDe5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDJFRDBENkZFQ0Y2MTFFOEE5OUNCODFENzIyODU1MzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDJFRDBENzBFQ0Y2MTFFOEE5OUNCODFENzIyODU1MzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMkVEMEQ2REVDRjYxMUU4QTk5Q0I4MUQ3MjI4NTUzMSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMkVEMEQ2RUVDRjYxMUU4QTk5Q0I4MUQ3MjI4NTUzMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv4HgdQAAD64SURBVHja7F0HfBzF1X/XT3fq3XKTewHjgmkB0x0IBkIoAZIQEggJnSTABwQ+AqmQEOoHSSAJIQQIxbRgIDamYweDwQbbuNuyZcuSrH69fu+/OyedTrd7RSdbQvP3b3yn252Z3dnZ+c97894bA+0HXLNgiZE/lnJ68L5F858bwHrs/HEvp+1czx00SBCNRklCQkJCYnjCsJ+I91L++KP480FO1zIx+nNcxyT+eJbTTE4uTlO5jl2SeCUkJCQk9ieM+4F0i/njl3E/XcFpGf8+IYd1nMsfnwjSBfI53SEft4SEhITEsCNexnWcyvGluDwv9tscTh8zYZ7aT8K1cIJq+V8gWwPL83lOc+zwt/nYQfKRS0hISEgMG+Jl4hvBHz9WRNAiG42bWkSTDyolg3oVkIT/zef8LydDFmWDzN/AV/xtthhp1IRipR6TSSkO//1GPnIJCQkJieEk8ULadUISLa92UDQSZanXRgcdXkl2R7dk+gtOTzKRWjMg3Wn8sYLT0fjbkW+hMZNKyJ5npgjXUVBii526gM89VD52CQkJCYkvPfEy4Tn54wcxaddiNTEpqsdsdhMdeEg5lVR2q57P4/Qa5ylMo9zD+ONdTuPwd2mlg0aOK4pJuRQORwi2TCZztxB9lXzsEhISEhLDQeK9gJNCpCUVKsFGwj3WvUYmyokHFFNNbX7sp+M5LWFiLdIh3SP4401O5ZCiq0YVUFmVo/s4CBd1wIq4oKhb6v0m56uUj15CQkJCYkgSbwbrsZfhP6iUbXazkEZ7u9WAPEeNL6Cxk7u5Fmrh17kOR5J6lWOcHAajgQm7iAp7VMrd0m6SO4UK+/s5vjcJCQkJCYmBJ14mprH88bxQI+udB1chxaK4sMQeR4zJ/VmrRjmodmpx7M/DSV3zNcaVV8sf/0ZxIN2RtYXKum4iwsEe4oXk6yjoXjY+O417m02qdbSEhISEhMSgkXiP5HQGp/cFCWvhGzGJNk7lS1HmxUgkeYbKmjwaNaF7iffrnH4lCNEhSLcS5Y0YU0B5TkvSMoLBcK+/bXmm2Ne5XM5oHdI9E/eE6xbRryQkJCQkJAYF8R4lPmeR6od7gsZ5IGeyOyzKWm4vqTSkHcWpZqxTsX4WuJHLn09qCMgD8UPFiHxyFmgbP4eCvVkdVtRxOD0J4Zo4/Zq/LuSEisHoc2U3kZCQkJAYLMR7cNx3+NEuZuK6jZM5jswg4h6C78lIMpEcE1E7tTDmagTGRlznS/AH1nOLyvSF0YC/t8QL1yJbj9vSvATShQT8H04/SyjmENlNJCQkJCT2O/FCOuyRPB1kyzPHyvs5p//y8Vi4RnwqjGvviSIVR7z6cYuNRoMSZENA0T0jOEZFTb5uvmAgnDQmst1u7kWoWDvmdDF//ZyTIrFjvdjac95M2U0kJCQkJAaDxAu/WUUPbHNYaMah5UyGjnhJ+FMmtEdJXZ9V5NU40utFvBF9oZclXhONGt/j0gu3IRCyHvy+UPIb7vHnHc/XByOrjzj9hVMRrhHuSEjwLRaYIbuJhISEhESuYO5H3hHdZGYwUDhMSghIrMluXttGQX8YDPe92DkWi4kMGmQZDESY6PTnANVjHNSw00V5LFkns2BOl3iptxD8bDe5c7mVI/MVyb2txRu/Fl0ju4mEhISExGAg3m5/H0iKAV9EiUZVUGyhmUdUUPNuL+3c0tkdJMNiM2kWhLypiBcS7rgpxUzSqbfUgzWz1tpxpLeBlaK2RrSrolJ1vRjXG2DSNhq7rydPdhMJCQkJicFAvN0ipYEl3oA/QnkRo0KQSPDFrRiRR817vLRraxeZzdrECnUzrJvjwjomZ/oyK3W0hlJemMcV1DyGdV9symA2m6i43M6Em6e4OcXgdgVkr5CQkJCQGJTE29ktRSoRokzk9zL5OnskW6hrq0Y6qLLGQV5XiKXVvhJnDD5PhJyFvaXiUChCHrdflUBNRrKYTUo9eghzHp9Xm3gh4daMRcCNvhbWcDfyuoPd3xPvU0JCQkJCYn8Sb32PxKqqdUG89jxTbJs/6pGIiRwFalVQK/s5JVozQ2K2BSExR2nntlZq3OWmUAAqZjMZRYGQVsOREFntRqocUUgFRX21wF0d/sR1XAVWm0khW5td+5Y9TLoxS+hIT7jJetlNJCQkJCRyhWz2vYU181c5nUIiCAWsgLFOCtjyjExwppTlQPIN+qMs1TKZQtUcjlJbSxftqe8ks9GWMn+U/5ksEaqdWEEmocaGtNrZ7lNnFPyb2WoiKyeQbWLgjj6SMtff0ujuJl6fN0wBr6LWbuH0JKclnN66b9F8V38bPZmbk4SEhISEJN4Y0cKP5zhBtkgTE89BYIya2h53n4JiM5kt6XM6iGjdql3U3OAhh70goxuIRMM0bmoZE6xZCZiB7QChljZkOKVob/F2W0LD+rpjry/ZadBDL+e0mNQNGj5lIo4MJeLFevwRx5yKXZ0u5VTCaROne5e/88rOXNbDdeBBXs4J2zaiYZ/iOl6Qr5zEvsDJj+zB1qJnkeoyiRCzj71+SXV0GN0/AhrdTWpcekgy73G6mtvgM9k7hgbxPigG0J5MRhg62amk3E7OQqsSAxkqZK9bjRQF46rCUnPa5Lf6ox3UuLuDTEYzFTiLEyTRkKJejkQiipQbIw+jwURmE0uyRhP/GqaJB1Sm9O3VgscVUFXUgnSLSuxKHZCgY0nDSno2E++qoUS8Xzn2NGgqXqbei+W7OB3ExNiaI9KFPv8DUneXiseVXMeD8rWTGGDSuZlEbPc4/B+TzlXD5P5hwPJfjE8Jhzo4HcztsGUQXCMG65+Q6nIKdelSTjfytbUNh2eUTgCNhtiXMZOK6MBDK2ju0SNo0owSKh+RpxhTwfPG7jAqZGu1GRVicXWE0rqA7ZubFdJVSJYJNhRmkmOy9fi6qMPVQl2edvL63RQxBMlqNzDRWyi/yEKOQiNZHGGKmnxKvt07tJ+Xq9NPTQ0uatrt6ibYGAL+EHXxcRCuw2mh8kqnoprGmjBcjKpHF7BEXUpjJ5dQRY0zFr4yhqYh+MzvpL4WaiM53ZbDOs5PQrpK3UzKDkkNEgM4oFeTGj0vEVfysTnDpBnOT0K6APZbvXmQXOMvOf2B1ABF2L3uh5wW8zMyD4cHlM5N7o19gYuQnhQLNa9imRw1MRlGld2HDDrU7mfS27K+N3e5PCoJ2+wWqq4qpaJiJznz87KWZr2eILm7Ar2kW5QVixsNybaswqm6O+lUASK22vKU830eV5+2GUI4UOP3HzAp/oIl0n7dE5eBVrxe4zC2j5zK6RNJERIDBGwjqhVh55hh0veOStE++3tyVKAxRmBDmlM5vSiJN45c4GJjMKVBgAaVhFOhbvPe3pvVM/IL86hmVLlCuLlAIEkEK0i5MeJF0I9MAHelmNrmvkXzv0xOvzARx7rvr/pZzomkH2YzQhIDAp70gHAQWxwGCmt5EjUcrfiKdY4VDZM20Bt8TYPg+jD51tpWbsZAEi+TPrR7YzhteP2S6tb91QDpqJr3dJNOWPs9xrKllo+uZsG72nt6g9lE4yfV0LQDx+aMdJUbNBnT+i1t4u1pg6Yv4Qt7FQ/etn6WcZ2kwP1CulDtbyY19jg2/PiYfxspW2ZYYqXOsRWD4Pqc+3piwIRr4vQnUt1Dl3HazX9fPpiJt1vijSQhXvyG9dz2vUHqaFE/Pa4wpbIfggo4Fugiz2GjA2fWUllFYe6fcL6Vpe+e24SaOV9nD98MJN69X8IXtpLTBf0Y/DFb/aoc9/Y56ULKe0XM5GPAeuY/ZOsMSzzOKZkBFTQhvx2mbXIjpx/F/Q0B40Em36MGPfEmbloP0u1sC/WKnwzCRSANkLEe+Xo9qpGTw2mnaTPGktVmGZgbNBkUP2OEhkQqr3J2+/1mg8iXW+IFfiLWabPBtXLM2y84k1NFkt+P52c5XjbP8MLrl1TDCOV4Ui2FY9jA6SQ+tm6YNssVGr9ftD8uJuUa732L5u+9ZsES+AmZQqHey3MeV0STXBGZStn8IC85yWG/XIvVTJOnj+olkXaDh/6Rk/KparyTnMVMykygwUiEvL4wdj6igCdMXib9riY/dTUG4kM89i3KYFB2H0oFH0vhsHqGVAySRnjJPhJvz5r0l5V4p3P6GqdXM5S6sIvTt+Swt18wJsWxrbKJhh357uCPE1miw7p2Hv+9Z5g3yQiN38cNSuIVaOZUHQpEEshT305GCQOpQbyRsEFZ07VYel/CqCn5NOvYKqoZ7SRLEkIGvXoCIerwBandF6AIwkjydezd4qHGdS5q2+nLujE62/2KKxTWquGCVFzWNyRlnNS/90vcSa/NlHgZ8JG0kISExGAiYLiJdMiW0JbLBj3xBuOCSKQTA0LvHIczj+z2OMKdWkhHnV5DZSX2lK3kZEkZqSrfTk1uH7WSn6qm5SvJ1RSgbcvbqHWbN+PGgD9yOCzq0XBfilvjbfoSd0aoKGcvf+eVT9OUdvNJtYiWkJCQkMgR8TZymhEv4cKfFz66UR2hV8ulKBKBxKt+t9iMNP/CWqodV5jx1MPE5DiiII8KbRba2eGmEEuq+ZVWmvH1KmrZ6qGNS1soIKJppQOol+HzC9ItKLQlnUjEWW43fcn7BqTe76R5LtZJigfyYkTgjUmkhrlEV4GRwBaeHDQOcL0Fot5CUS+kh01cb1cOysYsE6rgUlKVOX7RrxoGoysQXy+CU1SLtkA71PN1tgxwnVCV1nLKFwIAnnl4f7bDyY/sweAwTvRFPCe4pWxj6TKYg7IxJleJPmEU7dzCZXdlURYshBFIA+/OR1yGN4sycA0IcFEjrgfvG1xxwgnnwWJ1jjhnJR/356itS0XdpaItdnHZg0rbKKJwjSbVzgJqUpdIO/haA1mL2dcsWPIUf5yH7f1qp/a4wmErP68OsWnFbAaBuzrCVD7KQadePJ6c9v4HKwmEI7St1aWsA3f/5gnTukXN1LHLl5MGxhr3ti+6Xb9Oum/R/MXZlLOfQ0amWzkcoMfxIFefYmDEw9skBsd0AEk6rTCbXDY68ffFBADuMslcDeo4IQb0/VzutjQHckTNQehMfIf152OcHo4N6HwO3B1+QKqF92zqa4SITvY2p19xnrcyJBIMUN8U5SOYQTL3LQyQcPt4g9OzXMcGjXIQhew0TuWk7aOKgTL+BcAA/gCX+XCa1zsNQwCnrwvSTdb+sKh+kMv8Io3y8BxvITWQC9rxHVJjhX8edw4GjXM4Xc3pyCT3czuf/0eNQfB7/PGoRvW380B4m8bg/r+kWuRjMrQRZfC5z8Sdg754MfVEZTMneWavoW9xvlUZDtxmcb/f5TSPkrvbYEK2XPSJ57mO3SnKHEXqclHMpx6TlnM531tpXhMmFjeRGuu5JOEwwgQ+y+nXWEvmc2O+tzFDPlzbGXzsI42yj+UPreu4XTw/aNDOEpPeROD5PEJqGFCfzj0gYMpvSI3MN1bjNEwQEte/P+b0Yy67PkUboW/CaGu+eAcpyTjxhbhXtM9bXGYkE+K9nz+uQgjFKbN6PwN3Z1hZy00EdijSWt+F1XMpk+4p3xmXdB03W/hCYdrC5BtPbDC6+uK1vdS8yd1/cveFqW5Td2jKrOI0DyHiBe7iAe76FAMpBoxnMigzLeLlck8QL+DoNMsNipfsl3oSEZe7SJBuIt4QJHY0p79yGpVmvSC/m9KRULnuowTJZ2ppjInvhVxHMK6sB/jjyn50hbO5vIUpJgi/FJqPdHwr0eYYJ27kcgM6EvMWIYElTvK+x/me4HNAgtgN7KQU9aE9/pEj4sUk6pgk5z8uJn4niIF+TJrtcB3Xc2+aBIc+8XchVaYL1HGfqCeqUW6ye4J2YiLnaU9xTeeJNrSnuA6QFuIt/5jT5IRjeM5Tua5QhsT7uSBbexrtsJbTqVzH9iR1TBBl5WX5fqyGBB8jyoSyK8UYcWqGZWICvQCxstNlPUWdh4hPiUCIyPwik7JHrsVqUMi2sMSsSbpAxRgHLfjO+JySLmA3m6g6v/fzgtp4+ikVVDa+/yGCE6y6v+yqZuASoWrVw/UDoF6E6npxBqQLwLALMXoXCtLQkqC/ppEfEbeWCqllVAb13iCkpVT3tIA/3syCdElIWYnuEP11g7goBem+xOl/KP2ABiYxCL+qE4Tl+CSkS0J6/DvnO1oMyCelUd/FOVITlmuQLgmNx2sijcmgHe7hcn+YRt2niT4xIcPLRh0/JQ0vAiGtJrunMhJbuepcE44/kSbx4Tk/lIR0SdzToVk8khlp1g0cgHdWWG4n4qx+kC6ACHCzkrQPrKOXZUG6wBROfyFKz48XUHTq2MA+6YhnNZKzAARsViRdk1lbkM7Lt9D882rJbBoYY7JSh42siYTOVYF8neWpA2dEIiFq7qqj9Q3LaMXWf9O7G56idzY8SW+tf5w+2vE87Qx8QC2hjbTa8/fhEOwfHfqSFBLcITkm3flCush2VvZ1MRgkgyGFlucrWdZ7K1/3RJ17wkD4NPXP6vvkJINef6D3MjyUpL50AenwAY1jemtKZkFCB6VZT0WOulyqQWF+ln3iHjFIaxHc1Bz0Ca3BP5V7mdY1FQtiyJVENHYfjFGYyN6W5PdcjM+2hPYxCu3ehH6UeSyWLdJt4GaFlMIR6q+WdN7ZY8hmGbhwoRhVyxx9xyQjTwYOOLVC+eyLKO3p2Ervb3yanv3ot7R4zV9o5fbXaFPjCtrZuo7qW7+g3W0bqb5jDTUEPqYtvtfIH+nYxAPq55x+xqnyS0CyWk/2GrGOm4m0m5Xxi5BIc/HiXyxU1b2w/J1XPKTuo5xroENfo3P896QfJi/tdzAO/b2P1zWewYk5kCYvEdJrIt7m5EnRjulicy4enFgr/XQA+gQG/gv1iLmfEhnQpjMMUhaTnytyOKHJxeQwXfyIySwx7OGr/SwT676JG2p8m/Q3oEgHnZx8xgwuQpUIw9kz7+TDyqi81D7gT6HInnwSm1dsodrDexvf7m7fSK9+9hAtXfco1bWsoVBEXZ4qr6ygmQfPpmPmH08nnnKykg6fdyRNnDKZbD1+UDAQ+TWnOh5o7uFUNoSJ9xWdGfLZSQZoqJdO08iT7Yb3F1H6Kr1UuF3jd7w8aweg/U7XIDJIPd/QyYf1G0QTwprSdp0J0BOJgw2nbDc1xxrq/RrH9EIKwrIQ8W6hgsaWbnU6596cZOKDoA6wCQjmoL0fzPGz2zUAfeJsDclyXAqNAlSLaCsYLepZjf8rx9d7EQ1N5AnNRPyEaoXop9n0NSytnpfEMvuyFPm2i/cYBlVaVt1PYl0+XXPinnjNkShPSzNXEyN044xDK/bJUzAbDWQzm8gf6it4jZpTSLtWd1FnWyet2Poy7WjpGYPHT5pIXzl2HhPuHCoq0faOgXHUlg2baOWHK3gweY88bg+YGAYG3+GB9nIeYJ4dgp0XxgLHkeq2kYhrk7zkP9GYWaPRH9AadFLgwhTHYRkIIyhYMsLaFoYvpRrnHolwifwstiYM/q38O4yrYOiQahaIvajxAsNiFdbNU3TOHQPDIJSfqFrSkeDRT37IedrjiLpYDMpniLyYCcJ6+vWE+wBRzOTzsR59nY7EjfXh/8b93aXlAsRlwR1krkY5mBwcx3mb4s6HdfLLiYOewHxEM+PzdydcN9aAbxTEnQrtQrKFZSTuEyo+uGnczOX8J1cdH9arTIYni4lMqsENmodVYkBHnxihc+4suNkkcSmZn4JMr+Q8LXFEDVuHBaJPHCPa4xY+591ctQHXgaUSPfuDJdBwcZ2rhUoaSzq3UfreDNkABlrbxDs+O8WzQd9dmPBcfy82RigT5STDhyDZ+OGdVJelUEL7YFw8TKMMlH0651kTdz649UjxzBaIa3hBjKVp+/F2v2yI3GQRAiViNAf9EcUXF4ZVeph2ZMWAqZgjLg8ZTEYy5PWMozazMSnxwtjKMrqTXn37QfIEOpXfJk6dTGd9+zyaMFm1XMcascNiVoy18KgDXI6Xky8YVp4KSH3GjGlKvjPOO4fefG0xvfbiv8nn9cJQ4xkeWP4PxMSDQ2gIEW+HIN9kA/hcqA75ft4VAy7u83sa5SwUs/WMIIy4DtYj5UQrVs7zO0EqWmHfoDZ9OJnkxXnX6JCMT0yk/hr/DDnPj4WKUAsw9ngv4Tet9SAMxhdx+a6Ea2sXg29a0gzcvfi69KxU9/A529N8DKfpHLs0nnRF3T5MNIVk1udVExOHJzU0In9IQbgwTno+3kJd+D0HB8KPF4MmD5YY6Cfq9AlMNv8a89cVfrLQeN2gkQfHpybRTEzWUUN+P9FFhv/eKTQNfxrA919vbR3WwafGJhDCKvoxvv8XxWT42BxfC6TGHwqpNUZkGJzhkTBJ591L9lzhPtfF+bXq8iWzik6CWp0J9A3xpCvqxbjxjkg/6SMcptMK9y2a337NgiXobJbYtnixXYkAGF0Vlpp19+CdcEDu4iuENm0jz3OvU6huF0WDoXhRlAw2K5nHjSLL6TypLOkrDK1fs47+9vgfeNIQICufe84F31bUyQgIUmy3KuvDkJjbvAElJKUvCXnnWy1UU5inEPtej5VOOeM0OmzeV+jxP/+V1q5W3BHh5jGWB4qztVwrBimgfrxaY2aJ9dzYDPtyHWnx7izrPkynYy9N5joCIhBS1xM6ZWr5q+r5l53LZb+cpL57uT744B6hka8szd9i6kTPIHv+WjP6Rr739zSIfzO3yXpBMImYrUG8bSmu4/xECT9G9AN8/00axItB70weTF9LGFzDPKDD1/V0oYHpb5/w6PmlDjAm61FAskAQCEfJ9/9YjokXk5R5iQFD+O9NXBfGptc08g20nY3eMmLGwU0yMWJR1M1hETYykmDgrBfBqqTGTvl5/Q/jG2ltp/af/Z467vgzBTfX9SZdZY5toGggSMEN28hy+71U8My/yeDvUbVv27yFHrhTJd3i0hL6n1/cqpAuiHRSWSFV5edRqydAG/Z2UqPLl5R0ldmKmGBA8h1Z6KAJZQVUU1VJV990PZ244OR46eGf/djpZ59DqGVf0ji8gO9lijCA0vIf/S+X8WGW1eupuV7ROfZvnWOTsmyHl3UOv6lzrFhDeksGTFxuHmRdQEvq2Zgi39YsBnMtrEpGuvsIWuuBnYmkG0cIIGW9oBRFGfSJaiaXS/bTvettFvDBPryOF3SidOmp1gsG+Lr0tEo3CVV02sgkZBRmgyNi8ZoRkQq+uoqq2WpMGqGqW0bPgbQb2l5P7ideonBTa3oZwmFyvPEuWdesp/Yrv0+tFjM9dNe9CumWlJXSdT+/mSqZLEG25U6bsunC7i4PhSOpjcfMxt7zFaikJ5QW0K5OD33zu9+m/Px8evHp53AIhiRYaP/5EJJ6oUo9Q0N1CN9BRHWpyLG0C5TqHNukQ5JdPBmAMURVsjnfALRPpkY4DTrHfgGtCCZoQiW1mu/Hvx+ffbnG71a+zlqdfFqz6mzav46GHupz2CceFgEssNQALcMGrSAZOYaevcOg2NmI28HDbQMtkWM/EK/eM4MF/3Yh/WMtfAVfa2suiZdCcRslwGeX8lOv2xaW99+q3Fw7iopuvoJCO3aT6+GnKNygeles6mqhL1ztBL48oKCYZhWoGoGo2L7PvKeJSu/6E93H19nR1k42m42uuvE6hXRHFjkU9fIel5f2utMf78xJNlCAqnoUl2fkL6ec+XVq2dtC7y1VJsK38KC1mAfUD4bCCIJ1XL5emNHPSXIYIe1O1BkwXxigFz9V2DHfPpwFZxrvdnkaUubvYhIXtz3WtyDxPRMfRnGgIcJkar2oUEFvy6LYQhoeyLRPrEhx/HiRFGmbB3RMduEe86zY7m8gUKRDeO2DqK2D+6NSboMmfg7Q7Ghp5sqEYIKENenNQkKHAeXSxDjemaiaFeJNtRVg8vlw7rSt5jE1VHj9D+mh1u108qdL6H+2fEKPNm6lx5q2Kt+/xr/ds/1zioZ61NDLmhvps7Xq/s/fuvhCGjVmNFUX5Cmku7szM9JNJN7g5yxRX/8b2nv+1dR6xa1U+slqKrBZ6PyLvksjx4yOtfGfeGAzDaGB5B4dctTqeA8MMWOyfTWRAXmuTvdNIdXgC+vWn2ECxOlr++hS5ZaO+w7vU/oGiIWChO/C5JYH9Dc5HSGbcL/g8QzOha0A3LOwRLGbn9kNnCzZEK/iFhDwZ25QGMltZEgyFhVQ9SknUCQJn4f5t5ebd9Kt9WspGI0ovi2P+9Qlg2kzDuCZ/TxlNyMYUSlbCnoz1+zFVM3BDVup/ef3UnDjNop6vBSub6Cue/5KlZ9+RnarlS689AcsCSsXCX/fC4dQB3smhWolEbDM/Yt8LzUBf8Js1IUwToL7zS9lE355ICxes13fh8vfezyIXyZbcp8D8bHrs8iHJZw7OL0ZC2+ZCSU2Z0u8/mgk5y0we/ZszWOBQIDe6Giiuxo20odBH+2JhBUCPOs75yuqYFgkuwMhanJlZ0AYk3i9Ly/p2cA3Dr4X/sMStZ1qJ4ynuUd0G4peO1QMrYQldiYBCuB2Izfb1m5PxJ1GNKhs3WCwXPHdIXjrO+TT1yRfrOvfkGV2aM8eEr7HEvvumcEa/6QsyRdA1KtHMyVexagEO/RkClgHhyK5JV8hSfZBKBRSEvByWwM961V9daccMI3G1I6l0jwrmTgvDKGykrY5r1HUHWnrTHqOd3cjvf/GYtq57jOad/ThsZ+nU//Dje1LwGcwnZkJJLn75WuZknzxwmHdHFbj2bwMdwiL8qECrGndLZ+87kCOtf1jqa/vd7q4W8QPzgU0B0Suwy6fVvczw5ol7DLgh57N2vc3uD2PzsS4SpF4fd7Ml/Hg8wu/2Apn7p7f6tXJl818vh6uMBhNtE1I20cdp27WgU0UWvhaAuHsJgLx67vwFw6u7etp4SkrosbGRhaG1aA9EyeNp82bFI+LM/rxku1romjhgR6+s6l2WXkxMTqUhGabwkfxDG7XKtEXYA2JjjkyjeyIkISg+MmioumtlxTl4NIR5euOTG832T7CEn0GclizHy0CRHxD9AnsyZuOYdo0Qdxv5uBS9PpQQZqT8MGMiIag6cjimUHyvY6fGZYLEAXvOPHcQMjpaDV/lAnx7o7JNwgbaTSmrzUN+yK01+JX1lWNhv5rW9va2uipp55KSrrhONWv1eZQxDGj0UgHzp6puP1gK8IWT/YeG/GuRI6zTyH3eyvI2NETfMhgt1Ht9ZfShAljaW9rG63ZvpNauMsK4j1hiHXW+9Ig3ntyVJfejC7VjE2rH7sHY6MyIcH96c8ixeI5I7zct0g/rvMRGsTrzgHx6i0VIPrV3yVNDigBw2UOEvDvhBQ7SRDwBWJQ18KROSJePZuOKdR3k46hhi6Nd6GkH88MRPKCSNAMwDMAxpEIp3mxzuTpiIzXeFUJNsOpVGdI8Y9t6MrM6t7194UU9fUmybq6OrriiiuotbW3m1QwGCS/v/e5Zqs6XlfXjCCH00lOq5lc/iAFw9mrvXu5EhUV0HvHzaLNU0aT5ZCDKO+0E6jknlvJPLFWUYVXlJXS6NrxVDupO47AgUNJXciDLdQqesEMVmpFNMpmPqVzTHN/XLF3bJXG4dYh0s4NnJ7jdKaYQWsZYlVr/L5Xp/iJaV4D6uzUODyUVNxfBhKOcIL/7l84HUP6u0WNyFG1elorvbjrziHSrFqbTYxFPO0cPTc3NBic4FKEpcUtGqdWZbo+EFWJNzMDTW+bGm0M6makdBFY/gm1XX8HdT30T3L/4wW67LLL6JxzzqENGzb0IV2Pp+8Shcmktqdw61Ek3i5//9zA4iXejRs3UmvQT9ZzF1DxLVdR/g/OI1NN78hlqLNmdDdvwChi7BAbB+7dB9Juqhn38TrH5ulIvNuH2qDLBAj3g88yHOTWZ9l2idAKXjGdJzjS3Wj/EfHfSNtQLT9H1WzSOXa5COrRDf67RKha/zBEmlHrHUG/PmoAnhlsov6pcdiRFvFes2AJZs1w+lbEvVAoM4mxq6FHEt3d6VFiIKcDgyNPcdMJrFxDvnc+pNUrPuqlSlakaZZyk5EuYDSp43FspyETS6vuYE9+dyRAr7evoydbPqIPXdt5VpFO1CphWBWJ0KpVq8hqtdKMGTM0z4dqO2Gno6oh9t7DIjdZqDYssj+dw3pW6hw7hwf+2RrS7u06+VbQ0ITWDFwrlN5GHSn5SLHHbjpYpTO4nyUpcL/CmGGfyBQI0hHQIaenmGgRnWkxp49IjevwK9p3e+4OFPECt4jdhPbVe+xOWRmTLtYa4PBdaTYbFdLFDkWZwN0UoJA/QmabURkd6js85GUCrMq36675mseOpMDnPdLt3IIy+qBL1aqBgLGmGwppLw3GSs5zOLrl9YCIv1wfaKebdr5EraGe5bE5ztH085ELyGzQno/E4jRv3ryZOjs7adasWQr5al4Dn24292pm81B626GC5IEba4/Yuegk8TN2BDonlwEzuKw6nWD7aLM3+TgMfLAtIGZaMCyBf+xhOsW+PxjakK8bftzYZBxrH9hhZRHfr1fj3KtJO+B+vUbbuTgfNnOfo5FvER+HVfUHYqBGp1/G+RLXhhFl6wKNMu5GHckMpsSuQYhNjm0aazg9yOc9IrlSGzzQQxV5iSBUxAZ/G5suaJwL1aXWcsvuHElobq4H2pav65w2loaexi4GCA8/1TgG46iP+P4fF5oFqEU3cpt8kfAcsEaMHcqmi7FlIZ+zW+OZzeKPS7XeY3MK0sXDRtzDyvJqJ3ndQQp1BXqFjUwH0UiU2rd7qHxKj1YEBk5Q+8LSGRGkkvFv3mnH9yLe68fNoBWr3qQOn1dRL6eC3WhSHCcRnxkIspQamzL8sfHdXqQLfOLeSa+2r6HTSw7SkXiNyn68kHZBqAcddJD+vUfV/XvTmAUNZvKF2uRkHmARFs3Ifw+UocVTOhIs1AaZWNau5+v8dBCQ7gFC8o6tk34PxMe/v82f2EoMLgl+QViQTGfpFLdM59hzOsSLPvcjkWJoRFSshDbCFm/3a0wOsZa4ivO8LCRsDAIVYqJ0OPVeB36Yz9vNZS+SFKs5KC+LazNMtpr5d8T5XSsmRhi0qsVkV29yuTyHl3ZPCuIdylgsJp1aYWRnJb57/DweYmK9QnxXJv9x7xh2KbuPf/9QaAuaRPnF4hzYamhFK1xm1iFdzGJhrTWyrMpBJRV53cEzAgF96yoQc9MuD7U1+8gPv1/mnXUr99LYQ0tpypFlVDpalUDh0gN/WsRKRjQpGD9hTRTkBiI2jB9DhpJCijSylBsMkZ0J9KHq6XT5tk90rUmAKouNZtjzaVU4SB3tHd31xfCZJ3ms+zXehhTEa6CtW7dSe3s7zZw5k+x2fYNb+C93dfayWdkzVHuu1gbqOcRDpG4UnYsYv78ZJM32Q+prnIS12gUipQv0Gz1DN0iYN1P6xi5Y8kC0sYPjnm8DEya28dMK1mEXA046+KaQ7iWSDK9J+gQmMd/KsJw60t+xJ1Op9x0mEkx+z/+yNTjfm5fvDf39Jxlkw9r2q5wX/fjoJBNbg5h0Hp7h5Tyqt8aLme/cwhIblVaqRGkyq2IpdiRKhZrafJo6u0zZh7eiJo/83jCtXdJIz9+2jpb+cQt5O3okVlg8w+gKKujNLV20vrmDvmhSU+NF51PEH6Co16tEiRptzaNHJxxCRxeUa9Z9XGEF/W38XBplUu1Bmvc0Kp/euPVdhym54OltbqbmnXXKGm4yNLv99PHKlWQymXTXdmPwhyLU2NCLa2U0H21i36ujDsoEkBz+meKcyD66rdE5KucGvb2dRdv9KsMy5zDRJkoAN1JurMFrZI/WRK7UtdeL8JO5xA9IXc5JF4Nlv/F03udfCck0ExyX4/cY6un3jBrSLmbil+Q5LVRZ06MeNlvU01OFjcR58PUFUReV2mj0xEKadWQVjZ9WTFabibZ93EbP376O9m5P7WYZLiuhju+f2+u3crOV7hwzg56aeBhdXT2RziwdSWdzuoa/Pz3pMPrN6AOplM+ZIIi3btt2ijBpe+P21z0xP/lWoQc0m2jTJx/Sx/95merWriaf202GaISqPv0HTfvX+TT2kZPomPp/0bRqB0XM+lpjqJhR5/bN3VblO/eB1JgtQvuoLG8K8sVa8u/7UTfUt98S7jGpJMhkSGWsouf2lCzvlhy0J9ZM/5HGeWi3lzIoF7NfT0L7w7r8XOr/LjDv6Bzr1Cm/v6Svlz9VpCGtIBGuFPn0fKCTDXLbctAnHuAB/Nks7rM5hWSI/oBQlNdxatQ5FfYGPxPSe6bQI79Uba01fu5MQ+pF3ziHMttNKqZc3ZyDZ4axSdlv2ZiEdCHePgSvmamzS8lo7ll8NZkF8aYRvSoxwAZUx+Uj8mjGYRVUUmFXJN7X7t5E7Q2pA6L458ygzu+eQ4kLwbU2B51fNpquHzGZruV0Hn8fY+0JRDJdECPWeDesW99rrfWoehPNabdzA6hlFphs9NPqE+iseWfS2OkHkdlsoV2bN9Anbywiy79/SRWfPU0mf6eyaFsdaqTDNv6Ndu3aTltbXeQJJm+PrkBIqXPNqm7vkJyphfqBDzUGh89yKLnipdyqQXab08gPo6kfU+bRcrBGeZSQ/lLh5Qx/j+FtjcEBvyULZPAXyj6QR0TM0q9Ks90xs4SKF3G207GAfEnkSSwHEs98ym5ZBNeMfUnv0rlOnLNY4/Br/ex+y3T6TSpJTks1/moaGpagBkks0+gTwX70iV+mILzPNYgIef+TBkGFOcFNCBHVELTlSlJtL+4Q9eK3Wj7nt6Rvs6LlF75ehygXp7q8LPPF7g1jMGwp0tn3ORw3HmAt/eN+9EuMDceJqFdJTdQRuHtM7ZRiZYN7i6XnFLMgXq83nHXtkIInzSihqlFO8rtDtPShLWlZSXuPOpRar7+MwpXladdVXlNNI6tU750VH/TYIDTWbaO2XfX0regklpAvpkfHX0D/nPB9OqFoCllsNho5aSrNOfEUmnb4PCqvqqSJbX3b2xT0UMmmJQrpgnx3dnj6BOaA+ry9rU0h/TQH9X2BnyaZ8d3Ig2Fnjuu5PGFwQeNcnmyg1xicETULhjsP67zAsXKXcoKh0Dcy2KwBrlCJUuQXlELVLcq/MEHFBinhfD7WluR8WAceSqpVeLpqLhAHdog6mPP/bxrSe3x9AU4YKGeLAV5rgIOF82U65UBihWHY3SkkungJCBL3BM77PU6pJk1XJrk2WJU+159OxwMbJl03Jjl0Jx9bkyL7n5IM7GuFZKdXZ724n2hCn7gA1sJJzsdgdCzUjhlMyoJiYnkI57+VU1SPOEm1Tk/0s/wfPrY5g7YEAf+X04OcbuN0E6f7xW+x97g4U+0QAoSQamSYOA79go+lEgB+TmoI017dlTKIC851YDI0TYxR71NydTna7ociNnPsmo8XE5BM9smGoIM18xNF31QF0QRpF424w5ZnLjjo8ApFwPR5I+R1CaMqf5jqNqpteehxI9KKSgkhU8tjaOsX7bS3wUuHfXMUzTipOq27MITCZF/2EeW99yFZ6pJ4V3BlwdrR5J13GPkOP5hef/V1WvjEv3gSYaU7H7qX4A20+u3FZLZYaOaxJylEqweLp4WmPJvc1qRt8sm064geYQSuUZX5dip32JT15C2tXfTSMwtp0cIXYyqwkRiQEqyc9ykQUeuIY05Fp0M0HKgHFvI1LR2IurgeGO6g8WDd9wTXszzLcsyCSLA+UBH3YkCN+3F/dkbiso8WZUPF+nIahBHLNwZkL4j/FaGiTZXHIMgM1ntY54OVuDlOOtgtNA+farkbZXmPWC+Kn7EGhaV6uvnxksCydoZof4cgDKgtt3Nax+Vtz+K6YESHqEiwmF7BZSzJ1T2f/MieU0TZ6Hsv8aD3fJr5IF2cKu4V9/Q8DHPSzHug6BM+UeeONPJAYjxE1FdLqnFcgZC2MNjiOcFn/iMuryvDNoDEeqZ4Xos5f86t/LkOTJS0fLwP5DrX6uQdJ1S/uN8lQhpNp0600bdFe4EYn07caD7DezCKPhgfJKY52aQpLg8I63BxDZXUE/PZKzQduO+VXEbSyXYi8d4KRp8ys5SKylRCCgWj1NWuqlIRsWrLOlXFPveYajKatJkXls3rP22l0RMKqKw6L6kLEtyM1n7corwa5911UEbxnxWi63KTeVcDf7qUW4kU5lNo1AiKOHvUzfVr99Jvfn0DhcIBOuHkr9LUcVXk7minA75yDBVVpBPLIsrE+z0m4L7ay11fuYbaJn21z++wzo4wuTa1tNPPrvop+dWNG+7ggeUmdTKyf4lXQkJCIgekWyAmi/kaEno+E09AtlQS7oojXbD9ZTB+KiztkQLjIiQqRBsbuFOph1ubfORxBal6bD5986ppdO4102n20VUUzzkGJtrx04vI2xmkPRtcGV98pMBJgakTyXfILE4zKTBlQg/pcj3bl7XTljdcNL1GjQj27tI3lb16oUpOj3TVucnuwy+nqKG3S5a76kBqn5A8Gh/2+oXE+8xj/4yRLiSy38nuJiEhMURI1ZTGab8j7ZCVH0rS1Ua8Hy8cp6tHji/opRpOlGphsRwMhBXitehoaWP5PnqrgU65YALZ8kzU3OClhjqX4moUgyPfQuUjHLRlWQvVTCvIyU11Nvhp01st5GpSn/u0miNpa9On5PK30Rtvr6Af33J8RuV1jT6Mtpx6H5VsXkymgJs8FVNY0j2Jokbt+CP/ffcD+vD9bruKnyVb/5OQkJAYZISLYB4w3rLydwxgr5BqULgWRCoIGf6s15OqJtbC87I105B4SThNl5T3DQgRL/V2+/KmiF5VWmlXjLM8XUF69Z+qR8Vny5vJ5uhLVjUsFe/Z0EUrn9hNTevdFA1np4ptr/fR5y820qdPN3STrjJZMFrpK5POYtnVQNu2bKOH73uwT8znVPCVjqOGQ39E9Uf9lFqnLNAl3Q1r19HjD/9V+V5kGkOH5l9dKLuahITEICdd+KzCqBHjFYgAEgqMlj7h5OfjUEti3XFFCtLF2uhjskVTEK9wITqlqMzOEm3fNcD4dcGYS1GqsJFYrx01XpVg33lpB7386GZq3uWmopIe6/PYLkeQhguKrBTxhmn9f5pp2cM7acOSvQoJ+zq1XZcC7jC1bPPSlvda6cO/1dPq5/ZQ6/bkdhAVBWNp7rhTle9rV31Gf/rDfRTw514Tsu6zNfTAnX9QQloWOcto7mjYNhh+y218lexuEhISgxinpDieblS0O4XPrIQGYmIbZjb2ihHJt91U9gwQAmLMpShV2EiF7Goc1NHqV9Z731y4XfHfNce5J8XU0VBdFzIh2/KMZLUbye+NKKS7Z62r+zyr06RssgCEg1EKMkmH/JkFH5pcfSj5gl30ef3btHrlp3THLbfRpddeQ5XVudkwaMkrr9HCJ59WgnU47YV0+uEXUaGjjDaubuN28N3N5LvsvkXzV8puJyEhMQjhzkEZ2LnoDtmUaUi8pDoUU0Fxcl/o+DXfGHEG0yS9CdOLqbhcXQxG7OYNq1rJ6+4txVqsJsovsnbXZXcYqajUzGRsJke+iY8bKBKIUIClX1dzgLztwYxJN4aDRp9AB9d+TVE71+/YSbdfdxO9+sLLaW26oIX6uh101+2/pmcff1Ih3bLCEXT2vMsUiRf3M+HAYp48KLrp/5NdTkJCYpACYVb748YGt6cF/XHtGS5QKJUlsRVMqIfMmZdc8nN1hruJliU3atrlotIqB008oCitSmDJvGtbF+2uc3W7mCOUJCTg/EILS7mqAV2A6whB+i1NbrUF1XRHa24iGzZ0bKHlmxeSN6C6xmHP3GO/eiIdeezRVFxakjI/YjmvX7OO3lmylFZ9tLLbRWjq6IPpmBlfJ0tCOMmGHW7auVmJAzHv3ldO3G/b1Ul3IgkJCS2c/MieI0kNvDI1g2wgWmxwcguTrku2YhrjsNiFyFVZ4zDVTi1KSbzurgDt3t7JhGml6XPLUhJu/Djv7gzSzi2d1NmmvbYKQp4yq3TAiVch+pCPVu9cQpsbV1IkGu4mpjHjamn85Ik0cvRoKikrJZvNxvcSoc6OTtrb1Ex1W7fRhrVfkNvl6nWzpxz6XaopnkzhUIScBb0nDx0tQdqwWvEFfpCJ90pJvBISEoOUfDFIgIARDARBcBDoApsExNYiQQbw30UkMITh/BcT7i7ZcunDLGY2ppiqN/lgHZchFjbSnZoAG+vdVD3aSdjoB0U4WbrFjkXurqCy7tvZ6ievJ9RtZAUf4pHj8vfZzVvNdjpk3Gk0bcRRtGHPctra/KlCxiBWpHQQDodYUvdRMOinjqYw1X26mYxGE809aiw58229lAtQqQcD4aP35wPfn8E7JCQkhgQwSLwvUnr4gRxXMiVehDmjPKc5vQxijTccjlA0IgyvNNCyx6u4FJVV5SlSMwJTwXjKWWBREk1QrZ4hIQJGk5H2h0CWby+hg2tPodljT6LGzu20p30z7WndSS5/C4XI2y0Ng6idtiIqdBbThrpPKBQKKCpnrBePtR9P7fU2ctgLFOl49YqddMSxE5QgIcFAVNmtCSp1Jt6psttJSEhIDG/inRiTNtMB3IlAjhCcwiypmnXCPBaUWGnLunZFokWQDK87rISfRH74A6uRsFSJGoS8v7WgRoOJRhRNUFKjqYs62/w0aUbfTRnyC020p7mOmttV7coY+7E00nmwQrqqhsDEUrCBdte3U83oEvKIWNcmkzJLschuJyEhITF8ASaoVUghif+u3xeh9pYgBXyRPuQbL6lqYcSYfGV3o23rO2jjZ62KxW9RmYUcBSZFEjYx8Vq4XrvDpHwfXFCvB5JqItxdYZoyeq7yvcQykUbkzekm3VA4SD6/mwIhPzU1dJKro0eVLsqKyG4nISEhMbyJdxQiUyVuUICQkB4mmGgSmoipm7GBgh5ArtPnliuqZhhWYdOELWvamIgiissQksW2/yVdrWsHgv6+/sqQ9keXzFSlX1ONoorucrdRe1cLuTwd5At4mWTDLOEHe7WRKGub7HYSEhISwxdQNVfbHH21n3qbIMQMrLAJgrNQf23YZjfRhAOKh1zD2EWb4B5teb3vEbsq2aiERhbMpA7PVjIb8qjMMiUJeZvj2jNCfp9ikLZcdjsJCQmJ4U285VZr3/XdZKrnGKx2ztYZoG3r26luY7tirWvmBLWymSVFSMQgZ4SfhFoa0jRUyQZO+K4m4dpi6IkFHftb+U7q7kWJkmYkSRzneHUwvscsd+NVvCBLWFcrn9HY31HlHCXx97DyGen+Dehs81FJRU9Er71NHdSws4MQD2OS83QliJrX76Yd7nepxDKJHKYKMTmxKBJvMBBSCLijzR8rYqHsdhISEhLDm3jzk8VnBlE6C01MHhGV2OL4rpSJCMTU2e5TPv2+sJK+jAj4wwr5Fpaom0fAmttssigJBA/ShUuRK7KH9rhXUm3efBqZP4fsVodi3bxlYwNNmjqS2puxb7uycfsrsttJSEhIDG/idcInF2uRiQRstRmVBEvk+LVKSKIVNU4lBZhw6zYpO959wOkuTtArIxLHGZyOVa2XjaoUGlWlVvynlBaNSbLRbom2v+hZLzb0fDfEfu+xosZ/iJLFdWIV+35OG0ndNxepUyTc2AfNu92joHqG5bc9z0rBUKeyhuvze1h6VhfBgxEXjc07nkYVzCWbxS6uxUhBX5TqNu9lclbE+uvuWzQ/dC9JnzcJCQmJYUu8/oA3QC6yrvpgD1WPKSBslIDdguKhR4hxmx7sZVJ5EV+uWbAEC56/xzFHQT+8Z7heDwyUAgq5nUY9Dt2/5XRpntOiGGdli4jdRO7OgJHv7wj+86d8/X3ulO/lWyzxL921rcMyclwRFRY5mGyDLOH3hDT1RdrIaaqikY6DyWqxUTjCE5VQkAk6oFg5R7rCsHr+c6x9JCQkJCSGL4y+gKcdX7C+uXt7F61e3kSrP2ii+q0u6mwNKCrkUChjD5hfGwwGS0GxTfj9Zmm23Dubi4mrHYm/+3tLt1ncOEvtkGDzi5ToUodxOjvZeVzfe/xxfigYCe7c3M7Sv5/GTxrB+XsIv963jArNteQP+qijq4W63O2KChqkq7RtJNzEH1fI7iYhISEhYY5Go19Eo5HKUDik+J9aLXks4doUEt4dz4EG1X9XBIHoBtY8EyTEyfxxZmllHpVWOnpLmMLISdU6R7tdlWDxi/XinN0US9r5hTaF8FXVssrQBuE21WsiwNfi94SwzeEN/NezGuS7kO/rBL7+JxvrXaNA2GPGjiAvS715DivVbQlQXddSMhksVGwe3yd/OBx6nssIy+4mISEhIQEWfT8YCirq0TB8T/2uKKS1GAJBv1CZIiZxKOr3hTp83mDQ5w2Q1xNQ9tLFemcg6Ivppy8Gx8WMkRKlTJNZtXq2WEyKxKkkuym3N8X12OxmpWzF4tqi1mkyJZG++c+icsVq+WAm19laZQrJdzqnXwT84bb2vX7yu4zU0RymEuNUikRDtNnzCm33LiV/pLPXfIPTI7KrSUhISEjEiPcxf8DLUlm3QHYnrHSFpEYeXxe5vZ2K+rTT3foaE1Bxh6vl1g5XK/4G4SrGUR6fa4vIfxbiPsdveD/YgZ2WBM7UO4/vvYvTz/nrCE4L0FZ878+VWid/GDtnb3Atfe56jNa6ngAJw2f3uMfePf8T2dUkJCQkJAAzk8KmC49+6q8s8YJIbuO//8x/HxuJRA5H2MM4NHK6XHx/gNN3OU3DOqawUf6AJUZYUhXC0hluOOnGf97fcHV232dZOucz+SLDqyIpOGDWESv5Y476V5S8kRak2UzEH8huJiEhISERL/ECP2LCHQHSFX//zR/0KlvdCazmNI+P1+EP/oQu+jhOS0C8/oCvmb+/zIQEa6KvhsPRjvot7eTzqJJzMqtovz9IrXs7uY7QgN2c2+WjttYuJUSlFlqbPdS8W1Gtv8Xp2n5U90zC37jre9euWi7XdiUkJCQkeiReQaSJ5AD18zX8iZ3b/8bpST6nF0Py35CAv8rS8UzmGCP/7RfS4CqWfA9n8l20c0v7eIM5QC4mQGe+lcaMr1LWdndsa1J2/gECwQaqrikli9mes5uC2nzjup3U0e5WNi/YGW1Rdgkqryyi9lYX7axrwiWTw+GgSFCZezzJ6WK+9v5YeP2d1M2jobf+iNPjTLobZReTkJCQkIjHgG1PwORb7PZ2rrRZ8xQzX2weYLVamHjNLGbblJCLMNzCGjLgdDqpIL+gTzlQWYvwjccxMb4tyr4XHxZb312NsN7c2tbSLUkX5ZcpBlVYx87LN1FrS6fyN373BTzIcL/d5vxxMh/egYLcjF5CQkJimEu8A4H2rr1zmFzHB8Vm8QqJBoJMoghHib/8iiV1DG63m8wGmxLtKV1gt59gIlEHfb3U13CRijn8trd6BfGp8ZXF+ef6At7r8VV2BwkJCQmJgcb/CzAAgMnNiHBbpicAAAAASUVORK5CYII=';
63
- ?>
64
- <style type="text/css">
65
- #monsterinsights-settings-area {
66
- visibility: hidden;
67
- animation: loadMonsterInsightsSettingsNoJSView 0s 2s forwards;
68
- }
69
-
70
- @keyframes loadMonsterInsightsSettingsNoJSView{
71
- to { visibility: visible; }
72
- }
73
- </style>
74
- <!--[if IE]>
75
- <style>
76
- #monsterinsights-settings-area{
77
- visibility: visible !important;
78
- }
79
- </style>
80
- <![endif]-->
81
- <div id="<?php echo $id; ?>">
82
- <div id="monsterinsights-settings-area" class="monsterinsights-settings-area mi-container" style="font-family:'Helvetica Neue', 'HelveticaNeue-Light', 'Helvetica Neue Light', Helvetica, Arial, 'Lucida Grande', sans-serif;margin: auto;width: 750px;max-width: 100%;">
83
- <div id="monsterinsights-settings-error-loading-area">
84
- <div class="" style="text-align: center; background-color: #fff;border: 1px solid #D6E2EC; padding: 15px 50px 30px; color: #777777; margin: <?php echo esc_attr( $margin ); ?>">
85
- <div class="" style="border-bottom: 0;padding: 5px 20px 0;">
86
- <img class="" src="<?php echo esc_attr( $inline_logo_image ); ?>" alt="" style="max-width: 100%;width: 240px;padding: 30px 0 15px;">
87
- </div>
88
- <div id="monsterinsights-error-js">
89
- <h3 class="" style="font-size: 20px;color: #434343;font-weight: 500;line-height:1.4;"><?php esc_html_e( 'Ooops! It Appears JavaScript Didn’t Load', 'google-analytics-for-wordpress' ); ?></h3>
90
- <p class="info" style="line-height: 1.5;margin: 1em 0;font-size: 16px;color: #434343;padding: 5px 20px 20px;"><?php esc_html_e( 'There seems to be an issue running JavaScript on your website, which MonsterInsights is crafted in to give you the best experience possible.', 'google-analytics-for-wordpress' ); ?></p>
91
- <div style="display: none" id="monsterinsights-nojs-error-message">
92
- <div class="" style=" border: 1px solid #E75066;
93
- border-left: 3px solid #E75066;
94
- background-color: #FEF8F9;
95
- color: #E75066;
96
- font-size: 14px;
97
- padding: 18px 18px 18px 21px;
98
- font-weight: 300;
99
- text-align: left;">
100
- <strong style="font-weight: 500;" id="monsterinsights-alert-message"></strong>
101
- </div>
102
- <p class="" style="font-size: 14px;color: #777777;padding-bottom: 15px;"><?php esc_html_e( 'Copy the error message above and paste it in a message to the MonsterInsights support team.', 'google-analytics-for-wordpress' ); ?></p>
103
- </div>
104
- <a href="https://www.monsterinsights.com/docs/fix-javascript-error" target="_blank" style="margin-left: auto;background-color: #54A0E0;border-color: #3380BC;border-bottom-width: 2px;color: #fff;border-radius: 3px;font-weight: 500;transition: all 0.1s ease-in-out;transition-duration: 0.2s;padding: 14px 35px;font-size: 16px;margin-top: 10px;margin-bottom: 20px; text-decoration: none; display: inline-block;">
105
- <?php esc_html_e( 'Resolve This Issue', 'google-analytics-for-wordpress' ); ?>
106
- </a>
107
- </div>
108
- <div id="monsterinsights-error-browser" style="display: none">
109
- <h3 class="" style="font-size: 20px;color: #434343;font-weight: 500;"><?php esc_html_e( 'Your browser version is not supported', 'google-analytics-for-wordpress' ); ?></h3>
110
- <p class="info" style="line-height: 1.5;margin: 1em 0;font-size: 16px;color: #434343;padding: 5px 20px 20px;"><?php esc_html_e( 'You are using a browser which is no longer supported by MonsterInsights. Please update or use another browser in order to access the plugin settings.', 'google-analytics-for-wordpress' ); ?></p>
111
- <a href="https://www.monsterinsights.com/docs/browser-support-policy/" target="_blank" style="margin-left: auto;background-color: #54A0E0;border-color: #3380BC;border-bottom-width: 2px;color: #fff;border-radius: 3px;font-weight: 500;transition: all 0.1s ease-in-out;transition-duration: 0.2s;padding: 14px 35px;font-size: 16px;margin-top: 10px;margin-bottom: 20px; text-decoration: none; display: inline-block;">
112
- <?php esc_html_e( 'View supported browsers', 'google-analytics-for-wordpress' ); ?>
113
- </a>
114
- </div>
115
- </div>
116
- </div>
117
- <div style="text-align: center;">
118
- <?php echo wp_kses_post( $footer ); ?>
119
- </div>
120
- </div>
121
- </div>
122
- <?php
123
- }
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * Callback to output the MonsterInsights settings page.
9
+ *
10
+ * @since 7.4.0
11
+ * @access public
12
+ *
13
+ * @return void
14
+ */
15
+ function monsterinsights_settings_page() {
16
+ echo monsterinsights_ublock_notice();
17
+ monsterinsights_settings_error_page( 'monsterinsights-vue-site-settings' );
18
+ monsterinsights_settings_inline_js();
19
+ }
20
+
21
+ function monsterinsights_network_page() {
22
+ echo monsterinsights_ublock_notice();
23
+ monsterinsights_settings_error_page( 'monsterinsights-vue-network-settings' );
24
+ monsterinsights_settings_inline_js();
25
+ }
26
+
27
+ /**
28
+ * Attempt to catch the js error preventing the Vue app from loading and displaying that message for better support.
29
+ */
30
+ function monsterinsights_settings_inline_js() {
31
+ ?>
32
+ <script type="text/javascript">
33
+ var ua = window.navigator.userAgent;
34
+ var msie = ua.indexOf( 'MSIE ' );
35
+ if ( msie > 0 ) {
36
+ var browser_error = document.getElementById( 'monsterinsights-error-browser' );
37
+ var js_error = document.getElementById( 'monsterinsights-error-js' );
38
+ js_error.style.display = 'none';
39
+ browser_error.style.display = 'block';
40
+ } else {
41
+ window.onerror = function myErrorHandler( errorMsg, url, lineNumber ) {
42
+ /* Don't try to put error in container that no longer exists post-vue loading */
43
+ var message_container = document.getElementById( 'monsterinsights-nojs-error-message' );
44
+ if ( ! message_container ) {
45
+ return false;
46
+ }
47
+ var message = document.getElementById( 'monsterinsights-alert-message' );
48
+ message.innerHTML = errorMsg;
49
+ message_container.style.display = 'block';
50
+ return false;
51
+ }
52
+ }
53
+ </script>
54
+ <?php
55
+ }
56
+
57
+
58
+ /**
59
+ * Error page HTML
60
+ **/
61
+ function monsterinsights_settings_error_page( $id = 'monsterinsights-vue-site-settings', $footer = '', $margin = '82px 0' ) {
62
+ $inline_logo_image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAd4AAABaCAYAAAAWyDe5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDJFRDBENkZFQ0Y2MTFFOEE5OUNCODFENzIyODU1MzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDJFRDBENzBFQ0Y2MTFFOEE5OUNCODFENzIyODU1MzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMkVEMEQ2REVDRjYxMUU4QTk5Q0I4MUQ3MjI4NTUzMSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMkVEMEQ2RUVDRjYxMUU4QTk5Q0I4MUQ3MjI4NTUzMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv4HgdQAAD64SURBVHja7F0HfBzF1X/XT3fq3XKTewHjgmkB0x0IBkIoAZIQEggJnSTABwQ+AqmQEOoHSSAJIQQIxbRgIDamYweDwQbbuNuyZcuSrH69fu+/OyedTrd7RSdbQvP3b3yn252Z3dnZ+c97894bA+0HXLNgiZE/lnJ68L5F858bwHrs/HEvp+1czx00SBCNRklCQkJCYnjCsJ+I91L++KP480FO1zIx+nNcxyT+eJbTTE4uTlO5jl2SeCUkJCQk9ieM+4F0i/njl3E/XcFpGf8+IYd1nMsfnwjSBfI53SEft4SEhITEsCNexnWcyvGluDwv9tscTh8zYZ7aT8K1cIJq+V8gWwPL83lOc+zwt/nYQfKRS0hISEgMG+Jl4hvBHz9WRNAiG42bWkSTDyolg3oVkIT/zef8LydDFmWDzN/AV/xtthhp1IRipR6TSSkO//1GPnIJCQkJieEk8ULadUISLa92UDQSZanXRgcdXkl2R7dk+gtOTzKRWjMg3Wn8sYLT0fjbkW+hMZNKyJ5npgjXUVBii526gM89VD52CQkJCYkvPfEy4Tn54wcxaddiNTEpqsdsdhMdeEg5lVR2q57P4/Qa5ylMo9zD+ONdTuPwd2mlg0aOK4pJuRQORwi2TCZztxB9lXzsEhISEhLDQeK9gJNCpCUVKsFGwj3WvUYmyokHFFNNbX7sp+M5LWFiLdIh3SP4401O5ZCiq0YVUFmVo/s4CBd1wIq4oKhb6v0m56uUj15CQkJCYkgSbwbrsZfhP6iUbXazkEZ7u9WAPEeNL6Cxk7u5Fmrh17kOR5J6lWOcHAajgQm7iAp7VMrd0m6SO4UK+/s5vjcJCQkJCYmBJ14mprH88bxQI+udB1chxaK4sMQeR4zJ/VmrRjmodmpx7M/DSV3zNcaVV8sf/0ZxIN2RtYXKum4iwsEe4oXk6yjoXjY+O417m02qdbSEhISEhMSgkXiP5HQGp/cFCWvhGzGJNk7lS1HmxUgkeYbKmjwaNaF7iffrnH4lCNEhSLcS5Y0YU0B5TkvSMoLBcK+/bXmm2Ne5XM5oHdI9E/eE6xbRryQkJCQkJAYF8R4lPmeR6od7gsZ5IGeyOyzKWm4vqTSkHcWpZqxTsX4WuJHLn09qCMgD8UPFiHxyFmgbP4eCvVkdVtRxOD0J4Zo4/Zq/LuSEisHoc2U3kZCQkJAYLMR7cNx3+NEuZuK6jZM5jswg4h6C78lIMpEcE1E7tTDmagTGRlznS/AH1nOLyvSF0YC/t8QL1yJbj9vSvATShQT8H04/SyjmENlNJCQkJCT2O/FCOuyRPB1kyzPHyvs5p//y8Vi4RnwqjGvviSIVR7z6cYuNRoMSZENA0T0jOEZFTb5uvmAgnDQmst1u7kWoWDvmdDF//ZyTIrFjvdjac95M2U0kJCQkJAaDxAu/WUUPbHNYaMah5UyGjnhJ+FMmtEdJXZ9V5NU40utFvBF9oZclXhONGt/j0gu3IRCyHvy+UPIb7vHnHc/XByOrjzj9hVMRrhHuSEjwLRaYIbuJhISEhESuYO5H3hHdZGYwUDhMSghIrMluXttGQX8YDPe92DkWi4kMGmQZDESY6PTnANVjHNSw00V5LFkns2BOl3iptxD8bDe5c7mVI/MVyb2txRu/Fl0ju4mEhISExGAg3m5/H0iKAV9EiUZVUGyhmUdUUPNuL+3c0tkdJMNiM2kWhLypiBcS7rgpxUzSqbfUgzWz1tpxpLeBlaK2RrSrolJ1vRjXG2DSNhq7rydPdhMJCQkJicFAvN0ipYEl3oA/QnkRo0KQSPDFrRiRR817vLRraxeZzdrECnUzrJvjwjomZ/oyK3W0hlJemMcV1DyGdV9symA2m6i43M6Em6e4OcXgdgVkr5CQkJCQGJTE29ktRSoRokzk9zL5OnskW6hrq0Y6qLLGQV5XiKXVvhJnDD5PhJyFvaXiUChCHrdflUBNRrKYTUo9eghzHp9Xm3gh4daMRcCNvhbWcDfyuoPd3xPvU0JCQkJCYn8Sb32PxKqqdUG89jxTbJs/6pGIiRwFalVQK/s5JVozQ2K2BSExR2nntlZq3OWmUAAqZjMZRYGQVsOREFntRqocUUgFRX21wF0d/sR1XAVWm0khW5td+5Y9TLoxS+hIT7jJetlNJCQkJCRyhWz2vYU181c5nUIiCAWsgLFOCtjyjExwppTlQPIN+qMs1TKZQtUcjlJbSxftqe8ks9GWMn+U/5ksEaqdWEEmocaGtNrZ7lNnFPyb2WoiKyeQbWLgjj6SMtff0ujuJl6fN0wBr6LWbuH0JKclnN66b9F8V38bPZmbk4SEhISEJN4Y0cKP5zhBtkgTE89BYIya2h53n4JiM5kt6XM6iGjdql3U3OAhh70goxuIRMM0bmoZE6xZCZiB7QChljZkOKVob/F2W0LD+rpjry/ZadBDL+e0mNQNGj5lIo4MJeLFevwRx5yKXZ0u5VTCaROne5e/88rOXNbDdeBBXs4J2zaiYZ/iOl6Qr5zEvsDJj+zB1qJnkeoyiRCzj71+SXV0GN0/AhrdTWpcekgy73G6mtvgM9k7hgbxPigG0J5MRhg62amk3E7OQqsSAxkqZK9bjRQF46rCUnPa5Lf6ox3UuLuDTEYzFTiLEyTRkKJejkQiipQbIw+jwURmE0uyRhP/GqaJB1Sm9O3VgscVUFXUgnSLSuxKHZCgY0nDSno2E++qoUS8Xzn2NGgqXqbei+W7OB3ExNiaI9KFPv8DUneXiseVXMeD8rWTGGDSuZlEbPc4/B+TzlXD5P5hwPJfjE8Jhzo4HcztsGUQXCMG65+Q6nIKdelSTjfytbUNh2eUTgCNhtiXMZOK6MBDK2ju0SNo0owSKh+RpxhTwfPG7jAqZGu1GRVicXWE0rqA7ZubFdJVSJYJNhRmkmOy9fi6qMPVQl2edvL63RQxBMlqNzDRWyi/yEKOQiNZHGGKmnxKvt07tJ+Xq9NPTQ0uatrt6ibYGAL+EHXxcRCuw2mh8kqnoprGmjBcjKpHF7BEXUpjJ5dQRY0zFr4yhqYh+MzvpL4WaiM53ZbDOs5PQrpK3UzKDkkNEgM4oFeTGj0vEVfysTnDpBnOT0K6APZbvXmQXOMvOf2B1ABF2L3uh5wW8zMyD4cHlM5N7o19gYuQnhQLNa9imRw1MRlGld2HDDrU7mfS27K+N3e5PCoJ2+wWqq4qpaJiJznz87KWZr2eILm7Ar2kW5QVixsNybaswqm6O+lUASK22vKU830eV5+2GUI4UOP3HzAp/oIl0n7dE5eBVrxe4zC2j5zK6RNJERIDBGwjqhVh55hh0veOStE++3tyVKAxRmBDmlM5vSiJN45c4GJjMKVBgAaVhFOhbvPe3pvVM/IL86hmVLlCuLlAIEkEK0i5MeJF0I9MAHelmNrmvkXzv0xOvzARx7rvr/pZzomkH2YzQhIDAp70gHAQWxwGCmt5EjUcrfiKdY4VDZM20Bt8TYPg+jD51tpWbsZAEi+TPrR7YzhteP2S6tb91QDpqJr3dJNOWPs9xrKllo+uZsG72nt6g9lE4yfV0LQDx+aMdJUbNBnT+i1t4u1pg6Yv4Qt7FQ/etn6WcZ2kwP1CulDtbyY19jg2/PiYfxspW2ZYYqXOsRWD4Pqc+3piwIRr4vQnUt1Dl3HazX9fPpiJt1vijSQhXvyG9dz2vUHqaFE/Pa4wpbIfggo4Fugiz2GjA2fWUllFYe6fcL6Vpe+e24SaOV9nD98MJN69X8IXtpLTBf0Y/DFb/aoc9/Y56ULKe0XM5GPAeuY/ZOsMSzzOKZkBFTQhvx2mbXIjpx/F/Q0B40Em36MGPfEmbloP0u1sC/WKnwzCRSANkLEe+Xo9qpGTw2mnaTPGktVmGZgbNBkUP2OEhkQqr3J2+/1mg8iXW+IFfiLWabPBtXLM2y84k1NFkt+P52c5XjbP8MLrl1TDCOV4Ui2FY9jA6SQ+tm6YNssVGr9ftD8uJuUa732L5u+9ZsES+AmZQqHey3MeV0STXBGZStn8IC85yWG/XIvVTJOnj+olkXaDh/6Rk/KparyTnMVMykygwUiEvL4wdj6igCdMXib9riY/dTUG4kM89i3KYFB2H0oFH0vhsHqGVAySRnjJPhJvz5r0l5V4p3P6GqdXM5S6sIvTt+Swt18wJsWxrbKJhh357uCPE1miw7p2Hv+9Z5g3yQiN38cNSuIVaOZUHQpEEshT305GCQOpQbyRsEFZ07VYel/CqCn5NOvYKqoZ7SRLEkIGvXoCIerwBandF6AIwkjydezd4qHGdS5q2+nLujE62/2KKxTWquGCVFzWNyRlnNS/90vcSa/NlHgZ8JG0kISExGAiYLiJdMiW0JbLBj3xBuOCSKQTA0LvHIczj+z2OMKdWkhHnV5DZSX2lK3kZEkZqSrfTk1uH7WSn6qm5SvJ1RSgbcvbqHWbN+PGgD9yOCzq0XBfilvjbfoSd0aoKGcvf+eVT9OUdvNJtYiWkJCQkMgR8TZymhEv4cKfFz66UR2hV8ulKBKBxKt+t9iMNP/CWqodV5jx1MPE5DiiII8KbRba2eGmEEuq+ZVWmvH1KmrZ6qGNS1soIKJppQOol+HzC9ItKLQlnUjEWW43fcn7BqTe76R5LtZJigfyYkTgjUmkhrlEV4GRwBaeHDQOcL0Fot5CUS+kh01cb1cOysYsE6rgUlKVOX7RrxoGoysQXy+CU1SLtkA71PN1tgxwnVCV1nLKFwIAnnl4f7bDyY/sweAwTvRFPCe4pWxj6TKYg7IxJleJPmEU7dzCZXdlURYshBFIA+/OR1yGN4sycA0IcFEjrgfvG1xxwgnnwWJ1jjhnJR/356itS0XdpaItdnHZg0rbKKJwjSbVzgJqUpdIO/haA1mL2dcsWPIUf5yH7f1qp/a4wmErP68OsWnFbAaBuzrCVD7KQadePJ6c9v4HKwmEI7St1aWsA3f/5gnTukXN1LHLl5MGxhr3ti+6Xb9Oum/R/MXZlLOfQ0amWzkcoMfxIFefYmDEw9skBsd0AEk6rTCbXDY68ffFBADuMslcDeo4IQb0/VzutjQHckTNQehMfIf152OcHo4N6HwO3B1+QKqF92zqa4SITvY2p19xnrcyJBIMUN8U5SOYQTL3LQyQcPt4g9OzXMcGjXIQhew0TuWk7aOKgTL+BcAA/gCX+XCa1zsNQwCnrwvSTdb+sKh+kMv8Io3y8BxvITWQC9rxHVJjhX8edw4GjXM4Xc3pyCT3czuf/0eNQfB7/PGoRvW380B4m8bg/r+kWuRjMrQRZfC5z8Sdg754MfVEZTMneWavoW9xvlUZDtxmcb/f5TSPkrvbYEK2XPSJ57mO3SnKHEXqclHMpx6TlnM531tpXhMmFjeRGuu5JOEwwgQ+y+nXWEvmc2O+tzFDPlzbGXzsI42yj+UPreu4XTw/aNDOEpPeROD5PEJqGFCfzj0gYMpvSI3MN1bjNEwQEte/P+b0Yy67PkUboW/CaGu+eAcpyTjxhbhXtM9bXGYkE+K9nz+uQgjFKbN6PwN3Z1hZy00EdijSWt+F1XMpk+4p3xmXdB03W/hCYdrC5BtPbDC6+uK1vdS8yd1/cveFqW5Td2jKrOI0DyHiBe7iAe76FAMpBoxnMigzLeLlck8QL+DoNMsNipfsl3oSEZe7SJBuIt4QJHY0p79yGpVmvSC/m9KRULnuowTJZ2ppjInvhVxHMK6sB/jjyn50hbO5vIUpJgi/FJqPdHwr0eYYJ27kcgM6EvMWIYElTvK+x/me4HNAgtgN7KQU9aE9/pEj4sUk6pgk5z8uJn4niIF+TJrtcB3Xc2+aBIc+8XchVaYL1HGfqCeqUW6ye4J2YiLnaU9xTeeJNrSnuA6QFuIt/5jT5IRjeM5Tua5QhsT7uSBbexrtsJbTqVzH9iR1TBBl5WX5fqyGBB8jyoSyK8UYcWqGZWICvQCxstNlPUWdh4hPiUCIyPwik7JHrsVqUMi2sMSsSbpAxRgHLfjO+JySLmA3m6g6v/fzgtp4+ikVVDa+/yGCE6y6v+yqZuASoWrVw/UDoF6E6npxBqQLwLALMXoXCtLQkqC/ppEfEbeWCqllVAb13iCkpVT3tIA/3syCdElIWYnuEP11g7goBem+xOl/KP2ABiYxCL+qE4Tl+CSkS0J6/DvnO1oMyCelUd/FOVITlmuQLgmNx2sijcmgHe7hcn+YRt2niT4xIcPLRh0/JQ0vAiGtJrunMhJbuepcE44/kSbx4Tk/lIR0SdzToVk8khlp1g0cgHdWWG4n4qx+kC6ACHCzkrQPrKOXZUG6wBROfyFKz48XUHTq2MA+6YhnNZKzAARsViRdk1lbkM7Lt9D882rJbBoYY7JSh42siYTOVYF8neWpA2dEIiFq7qqj9Q3LaMXWf9O7G56idzY8SW+tf5w+2vE87Qx8QC2hjbTa8/fhEOwfHfqSFBLcITkm3flCush2VvZ1MRgkgyGFlucrWdZ7K1/3RJ17wkD4NPXP6vvkJINef6D3MjyUpL50AenwAY1jemtKZkFCB6VZT0WOulyqQWF+ln3iHjFIaxHc1Bz0Ca3BP5V7mdY1FQtiyJVENHYfjFGYyN6W5PdcjM+2hPYxCu3ehH6UeSyWLdJt4GaFlMIR6q+WdN7ZY8hmGbhwoRhVyxx9xyQjTwYOOLVC+eyLKO3p2Ervb3yanv3ot7R4zV9o5fbXaFPjCtrZuo7qW7+g3W0bqb5jDTUEPqYtvtfIH+nYxAPq55x+xqnyS0CyWk/2GrGOm4m0m5Xxi5BIc/HiXyxU1b2w/J1XPKTuo5xroENfo3P896QfJi/tdzAO/b2P1zWewYk5kCYvEdJrIt7m5EnRjulicy4enFgr/XQA+gQG/gv1iLmfEhnQpjMMUhaTnytyOKHJxeQwXfyIySwx7OGr/SwT676JG2p8m/Q3oEgHnZx8xgwuQpUIw9kz7+TDyqi81D7gT6HInnwSm1dsodrDexvf7m7fSK9+9hAtXfco1bWsoVBEXZ4qr6ygmQfPpmPmH08nnnKykg6fdyRNnDKZbD1+UDAQ+TWnOh5o7uFUNoSJ9xWdGfLZSQZoqJdO08iT7Yb3F1H6Kr1UuF3jd7w8aweg/U7XIDJIPd/QyYf1G0QTwprSdp0J0BOJgw2nbDc1xxrq/RrH9EIKwrIQ8W6hgsaWbnU6596cZOKDoA6wCQjmoL0fzPGz2zUAfeJsDclyXAqNAlSLaCsYLepZjf8rx9d7EQ1N5AnNRPyEaoXop9n0NSytnpfEMvuyFPm2i/cYBlVaVt1PYl0+XXPinnjNkShPSzNXEyN044xDK/bJUzAbDWQzm8gf6it4jZpTSLtWd1FnWyet2Poy7WjpGYPHT5pIXzl2HhPuHCoq0faOgXHUlg2baOWHK3gweY88bg+YGAYG3+GB9nIeYJ4dgp0XxgLHkeq2kYhrk7zkP9GYWaPRH9AadFLgwhTHYRkIIyhYMsLaFoYvpRrnHolwifwstiYM/q38O4yrYOiQahaIvajxAsNiFdbNU3TOHQPDIJSfqFrSkeDRT37IedrjiLpYDMpniLyYCcJ6+vWE+wBRzOTzsR59nY7EjfXh/8b93aXlAsRlwR1krkY5mBwcx3mb4s6HdfLLiYOewHxEM+PzdydcN9aAbxTEnQrtQrKFZSTuEyo+uGnczOX8J1cdH9arTIYni4lMqsENmodVYkBHnxihc+4suNkkcSmZn4JMr+Q8LXFEDVuHBaJPHCPa4xY+591ctQHXgaUSPfuDJdBwcZ2rhUoaSzq3UfreDNkABlrbxDs+O8WzQd9dmPBcfy82RigT5STDhyDZ+OGdVJelUEL7YFw8TKMMlH0651kTdz649UjxzBaIa3hBjKVp+/F2v2yI3GQRAiViNAf9EcUXF4ZVeph2ZMWAqZgjLg8ZTEYy5PWMozazMSnxwtjKMrqTXn37QfIEOpXfJk6dTGd9+zyaMFm1XMcascNiVoy18KgDXI6Xky8YVp4KSH3GjGlKvjPOO4fefG0xvfbiv8nn9cJQ4xkeWP4PxMSDQ2gIEW+HIN9kA/hcqA75ft4VAy7u83sa5SwUs/WMIIy4DtYj5UQrVs7zO0EqWmHfoDZ9OJnkxXnX6JCMT0yk/hr/DDnPj4WKUAsw9ngv4Tet9SAMxhdx+a6Ea2sXg29a0gzcvfi69KxU9/A529N8DKfpHLs0nnRF3T5MNIVk1udVExOHJzU0In9IQbgwTno+3kJd+D0HB8KPF4MmD5YY6Cfq9AlMNv8a89cVfrLQeN2gkQfHpybRTEzWUUN+P9FFhv/eKTQNfxrA919vbR3WwafGJhDCKvoxvv8XxWT42BxfC6TGHwqpNUZkGJzhkTBJ591L9lzhPtfF+bXq8iWzik6CWp0J9A3xpCvqxbjxjkg/6SMcptMK9y2a337NgiXobJbYtnixXYkAGF0Vlpp19+CdcEDu4iuENm0jz3OvU6huF0WDoXhRlAw2K5nHjSLL6TypLOkrDK1fs47+9vgfeNIQICufe84F31bUyQgIUmy3KuvDkJjbvAElJKUvCXnnWy1UU5inEPtej5VOOeM0OmzeV+jxP/+V1q5W3BHh5jGWB4qztVwrBimgfrxaY2aJ9dzYDPtyHWnx7izrPkynYy9N5joCIhBS1xM6ZWr5q+r5l53LZb+cpL57uT744B6hka8szd9i6kTPIHv+WjP6Rr739zSIfzO3yXpBMImYrUG8bSmu4/xECT9G9AN8/00axItB70weTF9LGFzDPKDD1/V0oYHpb5/w6PmlDjAm61FAskAQCEfJ9/9YjokXk5R5iQFD+O9NXBfGptc08g20nY3eMmLGwU0yMWJR1M1hETYykmDgrBfBqqTGTvl5/Q/jG2ltp/af/Z467vgzBTfX9SZdZY5toGggSMEN28hy+71U8My/yeDvUbVv27yFHrhTJd3i0hL6n1/cqpAuiHRSWSFV5edRqydAG/Z2UqPLl5R0ldmKmGBA8h1Z6KAJZQVUU1VJV990PZ244OR46eGf/djpZ59DqGVf0ji8gO9lijCA0vIf/S+X8WGW1eupuV7ROfZvnWOTsmyHl3UOv6lzrFhDeksGTFxuHmRdQEvq2Zgi39YsBnMtrEpGuvsIWuuBnYmkG0cIIGW9oBRFGfSJaiaXS/bTvettFvDBPryOF3SidOmp1gsG+Lr0tEo3CVV02sgkZBRmgyNi8ZoRkQq+uoqq2WpMGqGqW0bPgbQb2l5P7ideonBTa3oZwmFyvPEuWdesp/Yrv0+tFjM9dNe9CumWlJXSdT+/mSqZLEG25U6bsunC7i4PhSOpjcfMxt7zFaikJ5QW0K5OD33zu9+m/Px8evHp53AIhiRYaP/5EJJ6oUo9Q0N1CN9BRHWpyLG0C5TqHNukQ5JdPBmAMURVsjnfALRPpkY4DTrHfgGtCCZoQiW1mu/Hvx+ffbnG71a+zlqdfFqz6mzav46GHupz2CceFgEssNQALcMGrSAZOYaevcOg2NmI28HDbQMtkWM/EK/eM4MF/3Yh/WMtfAVfa2suiZdCcRslwGeX8lOv2xaW99+q3Fw7iopuvoJCO3aT6+GnKNygeles6mqhL1ztBL48oKCYZhWoGoGo2L7PvKeJSu/6E93H19nR1k42m42uuvE6hXRHFjkU9fIel5f2utMf78xJNlCAqnoUl2fkL6ec+XVq2dtC7y1VJsK38KC1mAfUD4bCCIJ1XL5emNHPSXIYIe1O1BkwXxigFz9V2DHfPpwFZxrvdnkaUubvYhIXtz3WtyDxPRMfRnGgIcJkar2oUEFvy6LYQhoeyLRPrEhx/HiRFGmbB3RMduEe86zY7m8gUKRDeO2DqK2D+6NSboMmfg7Q7Ghp5sqEYIKENenNQkKHAeXSxDjemaiaFeJNtRVg8vlw7rSt5jE1VHj9D+mh1u108qdL6H+2fEKPNm6lx5q2Kt+/xr/ds/1zioZ61NDLmhvps7Xq/s/fuvhCGjVmNFUX5Cmku7szM9JNJN7g5yxRX/8b2nv+1dR6xa1U+slqKrBZ6PyLvksjx4yOtfGfeGAzDaGB5B4dctTqeA8MMWOyfTWRAXmuTvdNIdXgC+vWn2ECxOlr++hS5ZaO+w7vU/oGiIWChO/C5JYH9Dc5HSGbcL/g8QzOha0A3LOwRLGbn9kNnCzZEK/iFhDwZ25QGMltZEgyFhVQ9SknUCQJn4f5t5ebd9Kt9WspGI0ovi2P+9Qlg2kzDuCZ/TxlNyMYUSlbCnoz1+zFVM3BDVup/ef3UnDjNop6vBSub6Cue/5KlZ9+RnarlS689AcsCSsXCX/fC4dQB3smhWolEbDM/Yt8LzUBf8Js1IUwToL7zS9lE355ICxes13fh8vfezyIXyZbcp8D8bHrs8iHJZw7OL0ZC2+ZCSU2Z0u8/mgk5y0we/ZszWOBQIDe6Giiuxo20odBH+2JhBUCPOs75yuqYFgkuwMhanJlZ0AYk3i9Ly/p2cA3Dr4X/sMStZ1qJ4ynuUd0G4peO1QMrYQldiYBCuB2Izfb1m5PxJ1GNKhs3WCwXPHdIXjrO+TT1yRfrOvfkGV2aM8eEr7HEvvumcEa/6QsyRdA1KtHMyVexagEO/RkClgHhyK5JV8hSfZBKBRSEvByWwM961V9daccMI3G1I6l0jwrmTgvDKGykrY5r1HUHWnrTHqOd3cjvf/GYtq57jOad/ThsZ+nU//Dje1LwGcwnZkJJLn75WuZknzxwmHdHFbj2bwMdwiL8qECrGndLZ+87kCOtf1jqa/vd7q4W8QPzgU0B0Suwy6fVvczw5ol7DLgh57N2vc3uD2PzsS4SpF4fd7Ml/Hg8wu/2Apn7p7f6tXJl818vh6uMBhNtE1I20cdp27WgU0UWvhaAuHsJgLx67vwFw6u7etp4SkrosbGRhaG1aA9EyeNp82bFI+LM/rxku1romjhgR6+s6l2WXkxMTqUhGabwkfxDG7XKtEXYA2JjjkyjeyIkISg+MmioumtlxTl4NIR5euOTG832T7CEn0GclizHy0CRHxD9AnsyZuOYdo0Qdxv5uBS9PpQQZqT8MGMiIag6cjimUHyvY6fGZYLEAXvOPHcQMjpaDV/lAnx7o7JNwgbaTSmrzUN+yK01+JX1lWNhv5rW9va2uipp55KSrrhONWv1eZQxDGj0UgHzp6puP1gK8IWT/YeG/GuRI6zTyH3eyvI2NETfMhgt1Ht9ZfShAljaW9rG63ZvpNauMsK4j1hiHXW+9Ig3ntyVJfejC7VjE2rH7sHY6MyIcH96c8ixeI5I7zct0g/rvMRGsTrzgHx6i0VIPrV3yVNDigBw2UOEvDvhBQ7SRDwBWJQ18KROSJePZuOKdR3k46hhi6Nd6GkH88MRPKCSNAMwDMAxpEIp3mxzuTpiIzXeFUJNsOpVGdI8Y9t6MrM6t7194UU9fUmybq6OrriiiuotbW3m1QwGCS/v/e5Zqs6XlfXjCCH00lOq5lc/iAFw9mrvXu5EhUV0HvHzaLNU0aT5ZCDKO+0E6jknlvJPLFWUYVXlJXS6NrxVDupO47AgUNJXciDLdQqesEMVmpFNMpmPqVzTHN/XLF3bJXG4dYh0s4NnJ7jdKaYQWsZYlVr/L5Xp/iJaV4D6uzUODyUVNxfBhKOcIL/7l84HUP6u0WNyFG1elorvbjrziHSrFqbTYxFPO0cPTc3NBic4FKEpcUtGqdWZbo+EFWJNzMDTW+bGm0M6makdBFY/gm1XX8HdT30T3L/4wW67LLL6JxzzqENGzb0IV2Pp+8Shcmktqdw61Ek3i5//9zA4iXejRs3UmvQT9ZzF1DxLVdR/g/OI1NN78hlqLNmdDdvwChi7BAbB+7dB9Juqhn38TrH5ulIvNuH2qDLBAj3g88yHOTWZ9l2idAKXjGdJzjS3Wj/EfHfSNtQLT9H1WzSOXa5COrRDf67RKha/zBEmlHrHUG/PmoAnhlsov6pcdiRFvFes2AJZs1w+lbEvVAoM4mxq6FHEt3d6VFiIKcDgyNPcdMJrFxDvnc+pNUrPuqlSlakaZZyk5EuYDSp43FspyETS6vuYE9+dyRAr7evoydbPqIPXdt5VpFO1CphWBWJ0KpVq8hqtdKMGTM0z4dqO2Gno6oh9t7DIjdZqDYssj+dw3pW6hw7hwf+2RrS7u06+VbQ0ITWDFwrlN5GHSn5SLHHbjpYpTO4nyUpcL/CmGGfyBQI0hHQIaenmGgRnWkxp49IjevwK9p3e+4OFPECt4jdhPbVe+xOWRmTLtYa4PBdaTYbFdLFDkWZwN0UoJA/QmabURkd6js85GUCrMq36675mseOpMDnPdLt3IIy+qBL1aqBgLGmGwppLw3GSs5zOLrl9YCIv1wfaKebdr5EraGe5bE5ztH085ELyGzQno/E4jRv3ryZOjs7adasWQr5al4Dn24292pm81B626GC5IEba4/Yuegk8TN2BDonlwEzuKw6nWD7aLM3+TgMfLAtIGZaMCyBf+xhOsW+PxjakK8bftzYZBxrH9hhZRHfr1fj3KtJO+B+vUbbuTgfNnOfo5FvER+HVfUHYqBGp1/G+RLXhhFl6wKNMu5GHckMpsSuQYhNjm0aazg9yOc9IrlSGzzQQxV5iSBUxAZ/G5suaJwL1aXWcsvuHElobq4H2pav65w2loaexi4GCA8/1TgG46iP+P4fF5oFqEU3cpt8kfAcsEaMHcqmi7FlIZ+zW+OZzeKPS7XeY3MK0sXDRtzDyvJqJ3ndQQp1BXqFjUwH0UiU2rd7qHxKj1YEBk5Q+8LSGRGkkvFv3mnH9yLe68fNoBWr3qQOn1dRL6eC3WhSHCcRnxkIspQamzL8sfHdXqQLfOLeSa+2r6HTSw7SkXiNyn68kHZBqAcddJD+vUfV/XvTmAUNZvKF2uRkHmARFs3Ifw+UocVTOhIs1AaZWNau5+v8dBCQ7gFC8o6tk34PxMe/v82f2EoMLgl+QViQTGfpFLdM59hzOsSLPvcjkWJoRFSshDbCFm/3a0wOsZa4ivO8LCRsDAIVYqJ0OPVeB36Yz9vNZS+SFKs5KC+LazNMtpr5d8T5XSsmRhi0qsVkV29yuTyHl3ZPCuIdylgsJp1aYWRnJb57/DweYmK9QnxXJv9x7xh2KbuPf/9QaAuaRPnF4hzYamhFK1xm1iFdzGJhrTWyrMpBJRV53cEzAgF96yoQc9MuD7U1+8gPv1/mnXUr99LYQ0tpypFlVDpalUDh0gN/WsRKRjQpGD9hTRTkBiI2jB9DhpJCijSylBsMkZ0J9KHq6XT5tk90rUmAKouNZtjzaVU4SB3tHd31xfCZJ3ms+zXehhTEa6CtW7dSe3s7zZw5k+x2fYNb+C93dfayWdkzVHuu1gbqOcRDpG4UnYsYv78ZJM32Q+prnIS12gUipQv0Gz1DN0iYN1P6xi5Y8kC0sYPjnm8DEya28dMK1mEXA046+KaQ7iWSDK9J+gQmMd/KsJw60t+xJ1Op9x0mEkx+z/+yNTjfm5fvDf39Jxlkw9r2q5wX/fjoJBNbg5h0Hp7h5Tyqt8aLme/cwhIblVaqRGkyq2IpdiRKhZrafJo6u0zZh7eiJo/83jCtXdJIz9+2jpb+cQt5O3okVlg8w+gKKujNLV20vrmDvmhSU+NF51PEH6Co16tEiRptzaNHJxxCRxeUa9Z9XGEF/W38XBplUu1Bmvc0Kp/euPVdhym54OltbqbmnXXKGm4yNLv99PHKlWQymXTXdmPwhyLU2NCLa2U0H21i36ujDsoEkBz+meKcyD66rdE5KucGvb2dRdv9KsMy5zDRJkoAN1JurMFrZI/WRK7UtdeL8JO5xA9IXc5JF4Nlv/F03udfCck0ExyX4/cY6un3jBrSLmbil+Q5LVRZ06MeNlvU01OFjcR58PUFUReV2mj0xEKadWQVjZ9WTFabibZ93EbP376O9m5P7WYZLiuhju+f2+u3crOV7hwzg56aeBhdXT2RziwdSWdzuoa/Pz3pMPrN6AOplM+ZIIi3btt2ijBpe+P21z0xP/lWoQc0m2jTJx/Sx/95merWriaf202GaISqPv0HTfvX+TT2kZPomPp/0bRqB0XM+lpjqJhR5/bN3VblO/eB1JgtQvuoLG8K8sVa8u/7UTfUt98S7jGpJMhkSGWsouf2lCzvlhy0J9ZM/5HGeWi3lzIoF7NfT0L7w7r8XOr/LjDv6Bzr1Cm/v6Svlz9VpCGtIBGuFPn0fKCTDXLbctAnHuAB/Nks7rM5hWSI/oBQlNdxatQ5FfYGPxPSe6bQI79Uba01fu5MQ+pF3ziHMttNKqZc3ZyDZ4axSdlv2ZiEdCHePgSvmamzS8lo7ll8NZkF8aYRvSoxwAZUx+Uj8mjGYRVUUmFXJN7X7t5E7Q2pA6L458ygzu+eQ4kLwbU2B51fNpquHzGZruV0Hn8fY+0JRDJdECPWeDesW99rrfWoehPNabdzA6hlFphs9NPqE+iseWfS2OkHkdlsoV2bN9Anbywiy79/SRWfPU0mf6eyaFsdaqTDNv6Ndu3aTltbXeQJJm+PrkBIqXPNqm7vkJyphfqBDzUGh89yKLnipdyqQXab08gPo6kfU+bRcrBGeZSQ/lLh5Qx/j+FtjcEBvyULZPAXyj6QR0TM0q9Ks90xs4SKF3G207GAfEnkSSwHEs98ym5ZBNeMfUnv0rlOnLNY4/Br/ex+y3T6TSpJTks1/moaGpagBkks0+gTwX70iV+mILzPNYgIef+TBkGFOcFNCBHVELTlSlJtL+4Q9eK3Wj7nt6Rvs6LlF75ehygXp7q8LPPF7g1jMGwp0tn3ORw3HmAt/eN+9EuMDceJqFdJTdQRuHtM7ZRiZYN7i6XnFLMgXq83nHXtkIInzSihqlFO8rtDtPShLWlZSXuPOpRar7+MwpXladdVXlNNI6tU750VH/TYIDTWbaO2XfX0regklpAvpkfHX0D/nPB9OqFoCllsNho5aSrNOfEUmnb4PCqvqqSJbX3b2xT0UMmmJQrpgnx3dnj6BOaA+ry9rU0h/TQH9X2BnyaZ8d3Ig2Fnjuu5PGFwQeNcnmyg1xicETULhjsP67zAsXKXcoKh0Dcy2KwBrlCJUuQXlELVLcq/MEHFBinhfD7WluR8WAceSqpVeLpqLhAHdog6mPP/bxrSe3x9AU4YKGeLAV5rgIOF82U65UBihWHY3SkkungJCBL3BM77PU6pJk1XJrk2WJU+159OxwMbJl03Jjl0Jx9bkyL7n5IM7GuFZKdXZ724n2hCn7gA1sJJzsdgdCzUjhlMyoJiYnkI57+VU1SPOEm1Tk/0s/wfPrY5g7YEAf+X04OcbuN0E6f7xW+x97g4U+0QAoSQamSYOA79go+lEgB+TmoI017dlTKIC851YDI0TYxR71NydTna7ociNnPsmo8XE5BM9smGoIM18xNF31QF0QRpF424w5ZnLjjo8ApFwPR5I+R1CaMqf5jqNqpteehxI9KKSgkhU8tjaOsX7bS3wUuHfXMUzTipOq27MITCZF/2EeW99yFZ6pJ4V3BlwdrR5J13GPkOP5hef/V1WvjEv3gSYaU7H7qX4A20+u3FZLZYaOaxJylEqweLp4WmPJvc1qRt8sm064geYQSuUZX5dip32JT15C2tXfTSMwtp0cIXYyqwkRiQEqyc9ykQUeuIY05Fp0M0HKgHFvI1LR2IurgeGO6g8WDd9wTXszzLcsyCSLA+UBH3YkCN+3F/dkbiso8WZUPF+nIahBHLNwZkL4j/FaGiTZXHIMgM1ntY54OVuDlOOtgtNA+farkbZXmPWC+Kn7EGhaV6uvnxksCydoZof4cgDKgtt3Nax+Vtz+K6YESHqEiwmF7BZSzJ1T2f/MieU0TZ6Hsv8aD3fJr5IF2cKu4V9/Q8DHPSzHug6BM+UeeONPJAYjxE1FdLqnFcgZC2MNjiOcFn/iMuryvDNoDEeqZ4Xos5f86t/LkOTJS0fLwP5DrX6uQdJ1S/uN8lQhpNp0600bdFe4EYn07caD7DezCKPhgfJKY52aQpLg8I63BxDZXUE/PZKzQduO+VXEbSyXYi8d4KRp8ys5SKylRCCgWj1NWuqlIRsWrLOlXFPveYajKatJkXls3rP22l0RMKqKw6L6kLEtyM1n7corwa5911UEbxnxWi63KTeVcDf7qUW4kU5lNo1AiKOHvUzfVr99Jvfn0DhcIBOuHkr9LUcVXk7minA75yDBVVpBPLIsrE+z0m4L7ay11fuYbaJn21z++wzo4wuTa1tNPPrvop+dWNG+7ggeUmdTKyf4lXQkJCIgekWyAmi/kaEno+E09AtlQS7oojXbD9ZTB+KiztkQLjIiQqRBsbuFOph1ubfORxBal6bD5986ppdO4102n20VUUzzkGJtrx04vI2xmkPRtcGV98pMBJgakTyXfILE4zKTBlQg/pcj3bl7XTljdcNL1GjQj27tI3lb16oUpOj3TVucnuwy+nqKG3S5a76kBqn5A8Gh/2+oXE+8xj/4yRLiSy38nuJiEhMURI1ZTGab8j7ZCVH0rS1Ua8Hy8cp6tHji/opRpOlGphsRwMhBXitehoaWP5PnqrgU65YALZ8kzU3OClhjqX4moUgyPfQuUjHLRlWQvVTCvIyU11Nvhp01st5GpSn/u0miNpa9On5PK30Rtvr6Af33J8RuV1jT6Mtpx6H5VsXkymgJs8FVNY0j2Jokbt+CP/ffcD+vD9bruKnyVb/5OQkJAYZISLYB4w3rLydwxgr5BqULgWRCoIGf6s15OqJtbC87I105B4SThNl5T3DQgRL/V2+/KmiF5VWmlXjLM8XUF69Z+qR8Vny5vJ5uhLVjUsFe/Z0EUrn9hNTevdFA1np4ptr/fR5y820qdPN3STrjJZMFrpK5POYtnVQNu2bKOH73uwT8znVPCVjqOGQ39E9Uf9lFqnLNAl3Q1r19HjD/9V+V5kGkOH5l9dKLuahITEICdd+KzCqBHjFYgAEgqMlj7h5OfjUEti3XFFCtLF2uhjskVTEK9wITqlqMzOEm3fNcD4dcGYS1GqsJFYrx01XpVg33lpB7386GZq3uWmopIe6/PYLkeQhguKrBTxhmn9f5pp2cM7acOSvQoJ+zq1XZcC7jC1bPPSlvda6cO/1dPq5/ZQ6/bkdhAVBWNp7rhTle9rV31Gf/rDfRTw514Tsu6zNfTAnX9QQloWOcto7mjYNhh+y218lexuEhISgxinpDieblS0O4XPrIQGYmIbZjb2ihHJt91U9gwQAmLMpShV2EiF7Goc1NHqV9Z731y4XfHfNce5J8XU0VBdFzIh2/KMZLUbye+NKKS7Z62r+zyr06RssgCEg1EKMkmH/JkFH5pcfSj5gl30ef3btHrlp3THLbfRpddeQ5XVudkwaMkrr9HCJ59WgnU47YV0+uEXUaGjjDaubuN28N3N5LvsvkXzV8puJyEhMQjhzkEZ2LnoDtmUaUi8pDoUU0Fxcl/o+DXfGHEG0yS9CdOLqbhcXQxG7OYNq1rJ6+4txVqsJsovsnbXZXcYqajUzGRsJke+iY8bKBKIUIClX1dzgLztwYxJN4aDRp9AB9d+TVE71+/YSbdfdxO9+sLLaW26oIX6uh101+2/pmcff1Ih3bLCEXT2vMsUiRf3M+HAYp48KLrp/5NdTkJCYpACYVb748YGt6cF/XHtGS5QKJUlsRVMqIfMmZdc8nN1hruJliU3atrlotIqB008oCitSmDJvGtbF+2uc3W7mCOUJCTg/EILS7mqAV2A6whB+i1NbrUF1XRHa24iGzZ0bKHlmxeSN6C6xmHP3GO/eiIdeezRVFxakjI/YjmvX7OO3lmylFZ9tLLbRWjq6IPpmBlfJ0tCOMmGHW7auVmJAzHv3ldO3G/b1Ul3IgkJCS2c/MieI0kNvDI1g2wgWmxwcguTrku2YhrjsNiFyFVZ4zDVTi1KSbzurgDt3t7JhGml6XPLUhJu/Djv7gzSzi2d1NmmvbYKQp4yq3TAiVch+pCPVu9cQpsbV1IkGu4mpjHjamn85Ik0cvRoKikrJZvNxvcSoc6OTtrb1Ex1W7fRhrVfkNvl6nWzpxz6XaopnkzhUIScBb0nDx0tQdqwWvEFfpCJ90pJvBISEoOUfDFIgIARDARBcBDoApsExNYiQQbw30UkMITh/BcT7i7ZcunDLGY2ppiqN/lgHZchFjbSnZoAG+vdVD3aSdjoB0U4WbrFjkXurqCy7tvZ6ievJ9RtZAUf4pHj8vfZzVvNdjpk3Gk0bcRRtGHPctra/KlCxiBWpHQQDodYUvdRMOinjqYw1X26mYxGE809aiw58229lAtQqQcD4aP35wPfn8E7JCQkhgQwSLwvUnr4gRxXMiVehDmjPKc5vQxijTccjlA0IgyvNNCyx6u4FJVV5SlSMwJTwXjKWWBREk1QrZ4hIQJGk5H2h0CWby+hg2tPodljT6LGzu20p30z7WndSS5/C4XI2y0Ng6idtiIqdBbThrpPKBQKKCpnrBePtR9P7fU2ctgLFOl49YqddMSxE5QgIcFAVNmtCSp1Jt6psttJSEhIDG/inRiTNtMB3IlAjhCcwiypmnXCPBaUWGnLunZFokWQDK87rISfRH74A6uRsFSJGoS8v7WgRoOJRhRNUFKjqYs62/w0aUbfTRnyC020p7mOmttV7coY+7E00nmwQrqqhsDEUrCBdte3U83oEvKIWNcmkzJLschuJyEhITF8ASaoVUghif+u3xeh9pYgBXyRPuQbL6lqYcSYfGV3o23rO2jjZ62KxW9RmYUcBSZFEjYx8Vq4XrvDpHwfXFCvB5JqItxdYZoyeq7yvcQykUbkzekm3VA4SD6/mwIhPzU1dJKro0eVLsqKyG4nISEhMbyJdxQiUyVuUICQkB4mmGgSmoipm7GBgh5ArtPnliuqZhhWYdOELWvamIgiissQksW2/yVdrWsHgv6+/sqQ9keXzFSlX1ONoorucrdRe1cLuTwd5At4mWTDLOEHe7WRKGub7HYSEhISwxdQNVfbHH21n3qbIMQMrLAJgrNQf23YZjfRhAOKh1zD2EWb4B5teb3vEbsq2aiERhbMpA7PVjIb8qjMMiUJeZvj2jNCfp9ikLZcdjsJCQmJ4U285VZr3/XdZKrnGKx2ztYZoG3r26luY7tirWvmBLWymSVFSMQgZ4SfhFoa0jRUyQZO+K4m4dpi6IkFHftb+U7q7kWJkmYkSRzneHUwvscsd+NVvCBLWFcrn9HY31HlHCXx97DyGen+Dehs81FJRU9Er71NHdSws4MQD2OS83QliJrX76Yd7nepxDKJHKYKMTmxKBJvMBBSCLijzR8rYqHsdhISEhLDm3jzk8VnBlE6C01MHhGV2OL4rpSJCMTU2e5TPv2+sJK+jAj4wwr5Fpaom0fAmttssigJBA/ShUuRK7KH9rhXUm3efBqZP4fsVodi3bxlYwNNmjqS2puxb7uycfsrsttJSEhIDG/idcInF2uRiQRstRmVBEvk+LVKSKIVNU4lBZhw6zYpO959wOkuTtArIxLHGZyOVa2XjaoUGlWlVvynlBaNSbLRbom2v+hZLzb0fDfEfu+xosZ/iJLFdWIV+35OG0ndNxepUyTc2AfNu92joHqG5bc9z0rBUKeyhuvze1h6VhfBgxEXjc07nkYVzCWbxS6uxUhBX5TqNu9lclbE+uvuWzQ/dC9JnzcJCQmJYUu8/oA3QC6yrvpgD1WPKSBslIDdguKhR4hxmx7sZVJ5EV+uWbAEC56/xzFHQT+8Z7heDwyUAgq5nUY9Dt2/5XRpntOiGGdli4jdRO7OgJHv7wj+86d8/X3ulO/lWyzxL921rcMyclwRFRY5mGyDLOH3hDT1RdrIaaqikY6DyWqxUTjCE5VQkAk6oFg5R7rCsHr+c6x9JCQkJCSGL4y+gKcdX7C+uXt7F61e3kSrP2ii+q0u6mwNKCrkUChjD5hfGwwGS0GxTfj9Zmm23Dubi4mrHYm/+3tLt1ncOEvtkGDzi5ToUodxOjvZeVzfe/xxfigYCe7c3M7Sv5/GTxrB+XsIv963jArNteQP+qijq4W63O2KChqkq7RtJNzEH1fI7iYhISEhYY5Go19Eo5HKUDik+J9aLXks4doUEt4dz4EG1X9XBIHoBtY8EyTEyfxxZmllHpVWOnpLmMLISdU6R7tdlWDxi/XinN0US9r5hTaF8FXVssrQBuE21WsiwNfi94SwzeEN/NezGuS7kO/rBL7+JxvrXaNA2GPGjiAvS715DivVbQlQXddSMhksVGwe3yd/OBx6nssIy+4mISEhIQEWfT8YCirq0TB8T/2uKKS1GAJBv1CZIiZxKOr3hTp83mDQ5w2Q1xNQ9tLFemcg6Ivppy8Gx8WMkRKlTJNZtXq2WEyKxKkkuym3N8X12OxmpWzF4tqi1mkyJZG++c+icsVq+WAm19laZQrJdzqnXwT84bb2vX7yu4zU0RymEuNUikRDtNnzCm33LiV/pLPXfIPTI7KrSUhISEjEiPcxf8DLUlm3QHYnrHSFpEYeXxe5vZ2K+rTT3foaE1Bxh6vl1g5XK/4G4SrGUR6fa4vIfxbiPsdveD/YgZ2WBM7UO4/vvYvTz/nrCE4L0FZ878+VWid/GDtnb3Atfe56jNa6ngAJw2f3uMfePf8T2dUkJCQkJAAzk8KmC49+6q8s8YJIbuO//8x/HxuJRA5H2MM4NHK6XHx/gNN3OU3DOqawUf6AJUZYUhXC0hluOOnGf97fcHV232dZOucz+SLDqyIpOGDWESv5Y476V5S8kRak2UzEH8huJiEhISERL/ECP2LCHQHSFX//zR/0KlvdCazmNI+P1+EP/oQu+jhOS0C8/oCvmb+/zIQEa6KvhsPRjvot7eTzqJJzMqtovz9IrXs7uY7QgN2c2+WjttYuJUSlFlqbPdS8W1Gtv8Xp2n5U90zC37jre9euWi7XdiUkJCQkeiReQaSJ5AD18zX8iZ3b/8bpST6nF0Py35CAv8rS8UzmGCP/7RfS4CqWfA9n8l20c0v7eIM5QC4mQGe+lcaMr1LWdndsa1J2/gECwQaqrikli9mes5uC2nzjup3U0e5WNi/YGW1Rdgkqryyi9lYX7axrwiWTw+GgSFCZezzJ6WK+9v5YeP2d1M2jobf+iNPjTLobZReTkJCQkIjHgG1PwORb7PZ2rrRZ8xQzX2weYLVamHjNLGbblJCLMNzCGjLgdDqpIL+gTzlQWYvwjccxMb4tyr4XHxZb312NsN7c2tbSLUkX5ZcpBlVYx87LN1FrS6fyN373BTzIcL/d5vxxMh/egYLcjF5CQkJimEu8A4H2rr1zmFzHB8Vm8QqJBoJMoghHib/8iiV1DG63m8wGmxLtKV1gt59gIlEHfb3U13CRijn8trd6BfGp8ZXF+ef6At7r8VV2BwkJCQmJgcb/CzAAgMnNiHBbpicAAAAASUVORK5CYII=';
63
+ ?>
64
+ <style type="text/css">
65
+ #monsterinsights-settings-area {
66
+ visibility: hidden;
67
+ animation: loadMonsterInsightsSettingsNoJSView 0s 2s forwards;
68
+ }
69
+
70
+ @keyframes loadMonsterInsightsSettingsNoJSView{
71
+ to { visibility: visible; }
72
+ }
73
+ </style>
74
+ <!--[if IE]>
75
+ <style>
76
+ #monsterinsights-settings-area{
77
+ visibility: visible !important;
78
+ }
79
+ </style>
80
+ <![endif]-->
81
+ <div id="<?php echo $id; ?>">
82
+ <div id="monsterinsights-settings-area" class="monsterinsights-settings-area mi-container" style="font-family:'Helvetica Neue', 'HelveticaNeue-Light', 'Helvetica Neue Light', Helvetica, Arial, 'Lucida Grande', sans-serif;margin: auto;width: 750px;max-width: 100%;">
83
+ <div id="monsterinsights-settings-error-loading-area">
84
+ <div class="" style="text-align: center; background-color: #fff;border: 1px solid #D6E2EC; padding: 15px 50px 30px; color: #777777; margin: <?php echo esc_attr( $margin ); ?>">
85
+ <div class="" style="border-bottom: 0;padding: 5px 20px 0;">
86
+ <img class="" src="<?php echo esc_attr( $inline_logo_image ); ?>" alt="" style="max-width: 100%;width: 240px;padding: 30px 0 15px;">
87
+ </div>
88
+ <div id="monsterinsights-error-js">
89
+ <h3 class="" style="font-size: 20px;color: #434343;font-weight: 500;line-height:1.4;"><?php esc_html_e( 'Ooops! It Appears JavaScript Didn’t Load', 'google-analytics-for-wordpress' ); ?></h3>
90
+ <p class="info" style="line-height: 1.5;margin: 1em 0;font-size: 16px;color: #434343;padding: 5px 20px 20px;"><?php esc_html_e( 'There seems to be an issue running JavaScript on your website, which MonsterInsights is crafted in to give you the best experience possible.', 'google-analytics-for-wordpress' ); ?></p>
91
+ <p class="info"style="line-height: 1.5;margin: 1em 0;font-size: 16px;color: #434343;padding: 5px 20px 20px;"><?php printf( esc_html__( 'If you are using an %sad blocker%s, please disable or whitelist the current page to load MonsterInsights correctly.', 'google-analytics-for-wordpress' ), '<strong>', '</strong>' ); ?></p>
92
+ <div style="display: none" id="monsterinsights-nojs-error-message">
93
+ <div class="" style=" border: 1px solid #E75066;
94
+ border-left: 3px solid #E75066;
95
+ background-color: #FEF8F9;
96
+ color: #E75066;
97
+ font-size: 14px;
98
+ padding: 18px 18px 18px 21px;
99
+ font-weight: 300;
100
+ text-align: left;">
101
+ <strong style="font-weight: 500;" id="monsterinsights-alert-message"></strong>
102
+ </div>
103
+ <p class="" style="font-size: 14px;color: #777777;padding-bottom: 15px;"><?php esc_html_e( 'Copy the error message above and paste it in a message to the MonsterInsights support team.', 'google-analytics-for-wordpress' ); ?></p>
104
+ </div>
105
+ <a href="https://www.monsterinsights.com/docs/fix-javascript-error" target="_blank" style="margin-left: auto;background-color: #54A0E0;border-color: #3380BC;border-bottom-width: 2px;color: #fff;border-radius: 3px;font-weight: 500;transition: all 0.1s ease-in-out;transition-duration: 0.2s;padding: 14px 35px;font-size: 16px;margin-top: 10px;margin-bottom: 20px; text-decoration: none; display: inline-block;">
106
+ <?php esc_html_e( 'Resolve This Issue', 'google-analytics-for-wordpress' ); ?>
107
+ </a>
108
+ </div>
109
+ <div id="monsterinsights-error-browser" style="display: none">
110
+ <h3 class="" style="font-size: 20px;color: #434343;font-weight: 500;"><?php esc_html_e( 'Your browser version is not supported', 'google-analytics-for-wordpress' ); ?></h3>
111
+ <p class="info" style="line-height: 1.5;margin: 1em 0;font-size: 16px;color: #434343;padding: 5px 20px 20px;"><?php esc_html_e( 'You are using a browser which is no longer supported by MonsterInsights. Please update or use another browser in order to access the plugin settings.', 'google-analytics-for-wordpress' ); ?></p>
112
+ <a href="https://www.monsterinsights.com/docs/browser-support-policy/" target="_blank" style="margin-left: auto;background-color: #54A0E0;border-color: #3380BC;border-bottom-width: 2px;color: #fff;border-radius: 3px;font-weight: 500;transition: all 0.1s ease-in-out;transition-duration: 0.2s;padding: 14px 35px;font-size: 16px;margin-top: 10px;margin-bottom: 20px; text-decoration: none; display: inline-block;">
113
+ <?php esc_html_e( 'View supported browsers', 'google-analytics-for-wordpress' ); ?>
114
+ </a>
115
+ </div>
116
+ </div>
117
+ </div>
118
+ <div style="text-align: center;">
119
+ <?php echo wp_kses_post( $footer ); ?>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ <?php
124
+ }
includes/admin/pages/tools.php CHANGED
@@ -1,44 +1,44 @@
1
- <?php
2
- // Exit if accessed directly
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit;
5
- }
6
-
7
- /**
8
- * MonsterInsights settings export.
9
- *
10
- * @since 6.0.0
11
- * @access public
12
- *
13
- * @return void
14
- */
15
- function monsterinsights_process_export_settings() {
16
- if ( ! isset( $_POST['monsterinsights_action'] ) || empty( $_POST['monsterinsights_action'] ) ) {
17
- return;
18
- }
19
-
20
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
21
- return;
22
- }
23
-
24
- if ( 'monsterinsights_export_settings' !== $_POST['monsterinsights_action'] ) {
25
- return;
26
- }
27
-
28
- if ( empty( $_POST['monsterinsights_export_settings'] ) || ! wp_verify_nonce( $_POST['monsterinsights_export_settings'], 'mi-admin-nonce' ) ) {
29
- return;
30
- }
31
-
32
- $settings = monsterinsights_export_settings();
33
- ignore_user_abort( true );
34
-
35
- nocache_headers();
36
- header( 'Content-Type: application/json; charset=utf-8' );
37
- header( 'Content-Disposition: attachment; filename=monsterinsights-settings-export-' . date( 'm-d-Y' ) . '.json' );
38
- header( "Expires: 0" );
39
-
40
- echo $settings;
41
- exit;
42
- }
43
-
44
- add_action( 'admin_init', 'monsterinsights_process_export_settings' );
1
+ <?php
2
+ // Exit if accessed directly
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ /**
8
+ * MonsterInsights settings export.
9
+ *
10
+ * @since 6.0.0
11
+ * @access public
12
+ *
13
+ * @return void
14
+ */
15
+ function monsterinsights_process_export_settings() {
16
+ if ( ! isset( $_POST['monsterinsights_action'] ) || empty( $_POST['monsterinsights_action'] ) ) {
17
+ return;
18
+ }
19
+
20
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
21
+ return;
22
+ }
23
+
24
+ if ( 'monsterinsights_export_settings' !== $_POST['monsterinsights_action'] ) {
25
+ return;
26
+ }
27
+
28
+ if ( empty( $_POST['monsterinsights_export_settings'] ) || ! wp_verify_nonce( $_POST['monsterinsights_export_settings'], 'mi-admin-nonce' ) ) {
29
+ return;
30
+ }
31
+
32
+ $settings = monsterinsights_export_settings();
33
+ ignore_user_abort( true );
34
+
35
+ nocache_headers();
36
+ header( 'Content-Type: application/json; charset=utf-8' );
37
+ header( 'Content-Disposition: attachment; filename=monsterinsights-settings-export-' . date( 'm-d-Y' ) . '.json' );
38
+ header( "Expires: 0" );
39
+
40
+ echo $settings;
41
+ exit;
42
+ }
43
+
44
+ add_action( 'admin_init', 'monsterinsights_process_export_settings' );
includes/admin/reporting.php CHANGED
@@ -1,68 +1,68 @@
1
- <?php
2
- /**
3
- * MonsterInsights Reporting.
4
- *
5
- * Handles aggregating data.
6
- *
7
- * @since 7.0.0
8
- *
9
- * @package MonsterInsights
10
- * @subpackage GA Reporting
11
- * @author Chris Christoff
12
- */
13
-
14
- // Exit if accessed directly
15
- if ( ! defined( 'ABSPATH' ) ) {
16
- exit;
17
- }
18
-
19
- final class MonsterInsights_Reporting {
20
-
21
- public $reports = array();
22
-
23
- public function __construct( ) {
24
-
25
- }
26
-
27
- public function add_report( $report = false ){
28
- if ( empty( $report ) || ! is_object( $report ) ) {
29
- return;
30
- }
31
-
32
- if ( version_compare( $report->version, '1.0.0', '<' ) ) {
33
- return;
34
- }
35
-
36
- $this->reports[] = $report;
37
- }
38
-
39
- public function get_aggregate_data() {
40
- if ( ! empty( $this->reports ) ) {
41
- foreach ( $this->reports as $report ) {
42
- $report->get_data( array( 'default' => true ) );
43
- }
44
- }
45
- }
46
-
47
- // $where possible values: auto, site, network, both
48
- public function delete_aggregate_data( $where = 'site' ) {
49
- if ( ! empty( $this->reports ) ) {
50
- foreach ( $this->reports as $report ) {
51
- $report->delete_cache( $where );
52
- }
53
- }
54
- }
55
-
56
- public function get_report( $name = '' ) {
57
- if ( empty( $name ) || empty( $this->reports ) ) {
58
- return false;
59
- }
60
-
61
- foreach ( $this->reports as $report ) {
62
- if ( $name === $report->name ) {
63
- return $report;
64
- }
65
- }
66
- return false;
67
- }
68
  }
1
+ <?php
2
+ /**
3
+ * MonsterInsights Reporting.
4
+ *
5
+ * Handles aggregating data.
6
+ *
7
+ * @since 7.0.0
8
+ *
9
+ * @package MonsterInsights
10
+ * @subpackage GA Reporting
11
+ * @author Chris Christoff
12
+ */
13
+
14
+ // Exit if accessed directly
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit;
17
+ }
18
+
19
+ final class MonsterInsights_Reporting {
20
+
21
+ public $reports = array();
22
+
23
+ public function __construct( ) {
24
+
25
+ }
26
+
27
+ public function add_report( $report = false ){
28
+ if ( empty( $report ) || ! is_object( $report ) ) {
29
+ return;
30
+ }
31
+
32
+ if ( version_compare( $report->version, '1.0.0', '<' ) ) {
33
+ return;
34
+ }
35
+
36
+ $this->reports[] = $report;
37
+ }
38
+
39
+ public function get_aggregate_data() {
40
+ if ( ! empty( $this->reports ) ) {
41
+ foreach ( $this->reports as $report ) {
42
+ $report->get_data( array( 'default' => true ) );
43
+ }
44
+ }
45
+ }
46
+
47
+ // $where possible values: auto, site, network, both
48
+ public function delete_aggregate_data( $where = 'site' ) {
49
+ if ( ! empty( $this->reports ) ) {
50
+ foreach ( $this->reports as $report ) {
51
+ $report->delete_cache( $where );
52
+ }
53
+ }
54
+ }
55
+
56
+ public function get_report( $name = '' ) {
57
+ if ( empty( $name ) || empty( $this->reports ) ) {
58
+ return false;
59
+ }
60
+
61
+ foreach ( $this->reports as $report ) {
62
+ if ( $name === $report->name ) {
63
+ return $report;
64
+ }
65
+ }
66
+ return false;
67
+ }
68
  }
includes/admin/reports/abstract-report.php CHANGED
@@ -1,437 +1,439 @@
1
- <?php
2
- /**
3
- * Report Abstract
4
- *
5
- * Ensures all of the reports have a uniform class with helper functions.
6
- *
7
- * @since 6.0.0
8
- *
9
- * @package MonsterInsights
10
- * @subpackage Reports
11
- * @author Chris Christoff
12
- */
13
-
14
- // Exit if accessed directly
15
- if ( ! defined( 'ABSPATH' ) ) {
16
- exit;
17
- }
18
-
19
- class MonsterInsights_Report {
20
-
21
- public $title;
22
- public $class;
23
- public $name;
24
- public $version = '1.0.0';
25
-
26
- /**
27
- * Primary class constructor.
28
- *
29
- * @access public
30
- * @since 6.0.0
31
- */
32
- public function __construct() {
33
- add_filter( 'monsterinsights_reports_abstract_get_data_pre_cache', array( $this, 'requirements' ), 10, 3 );
34
- }
35
-
36
- // Let's get the HTML to output for a particular report. This is not the AJAX endpoint. Args can hold things (generally start/end date range)
37
- protected function get_report_html( $args = array() ) {
38
- /* Defined in the report class */
39
- // For ajax, args start, end, and data will be set with the data to use. Else call $this->get_data( array( 'default' => true ) )
40
- return '';
41
- }
42
-
43
- public function additional_data() {
44
- return array();
45
- }
46
-
47
- public function requirements( $error = false, $args = array(), $name = '' ) {
48
- return $error;
49
- }
50
-
51
- public function show_report( $args = array() ) {
52
-
53
- if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
54
- return monsterinsights_get_message( 'error', esc_html__( 'Access denied', 'google-analytics-for-wordpress' ) );
55
- }
56
-
57
- if ( monsterinsights_get_option( 'dashboard_disabled', false ) ) {
58
- if ( current_user_can( 'monsterinsights_save_settings' ) ) {
59
- $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
60
-
61
- return monsterinsights_get_message( 'error',
62
- sprintf(
63
- esc_html__( 'Please %1$senable the dashboard%2$s to see report data.', 'google-analytics-for-wordpress' ),
64
- '<a href="' . $url . '">',
65
- '</a>'
66
- )
67
- );
68
- } else {
69
- return monsterinsights_get_message( 'error', esc_html__( 'The dashboard is disabled.', 'google-analytics-for-wordpress' ) );
70
- }
71
- }
72
-
73
- if ( monsterinsights_is_pro_version() ) {
74
- if ( ! MonsterInsights()->license->has_license() ) {
75
- $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
76
-
77
- return monsterinsights_get_message( 'error', esc_html__( 'You do not have an active license. Please %1$scheck your license configuration.%2$s', 'google-analytics-for-wordpress' ), '<a href="' . $url . '">', '</a>' );
78
- } else if ( MonsterInsights()->license->license_has_error() ) {
79
- return monsterinsights_get_message( 'error', $this->get_license_error() );
80
- }
81
- }
82
-
83
- if ( ! ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() ) ) {
84
- if ( current_user_can( 'monsterinsights_save_settings' ) ) {
85
- $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
86
-
87
- return monsterinsights_get_message( 'error',
88
- sprintf(
89
- esc_html__( 'Please %1$sauthenticate %2$swith Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),
90
- '<a href="' . $url . '">',
91
- '</a>'
92
- )
93
- );
94
- } else {
95
- return monsterinsights_get_message( 'error', esc_html__( 'The Google oAuth authentication needs to be re-authenticated to view data.', 'google-analytics-for-wordpress' ) );
96
- }
97
- }
98
-
99
- if ( ! MonsterInsights()->license->license_can( $this->level ) ) {
100
- return $this->get_upsell_notice();
101
- }
102
-
103
- $error = $this->requirements( false, array(), $this->name );
104
-
105
- if ( ! empty( $error ) ) {
106
- return monsterinsights_get_message( 'error', $error );
107
- }
108
-
109
- if ( ! empty( $args['error'] ) ) {
110
- return monsterinsights_get_message( 'error', $args['error'] );
111
- }
112
-
113
- if ( empty( $args['data'] ) || ! is_array( $args['data'] ) ) {
114
- if ( monsterinsights_is_pro_version() ) {
115
- return '';
116
- } else {
117
- // Try to get default data.
118
- $args = $this->get_data( array( 'default' => true ) );
119
- if ( empty( $args['data'] ) || is_array( $args['data'] ) ) {
120
- return monsterinsights_get_message( 'error', __( 'No data found', 'google-analytics-for-wordpress' ) );
121
- }
122
-
123
- if ( ! empty( $args['error'] ) ) {
124
- return monsterinsights_get_message( 'error', $data['error'] );
125
- }
126
- }
127
- }
128
-
129
- return $this->get_report_html( $args['data'] );
130
- }
131
-
132
- // Deletes the report data from the cache
133
- public function delete_cache( $where = 'site' ) {
134
-
135
- if ( $where === 'site' || $where === 'both' ) {
136
- delete_option( 'monsterinsights_report_data_' . $this->name );
137
- }
138
-
139
- if ( $where === 'network' || $where === 'both' ) {
140
- delete_option( 'monsterinsights_network_report_data_' . $this->name );
141
- }
142
- }
143
-
144
- // Get report data
145
- public function get_data( $args = array() ) {
146
-
147
- if ( ! empty( $args['default'] ) ) {
148
- $args['start'] = $this->default_start_date();
149
- $args['end'] = $this->default_end_date();
150
- }
151
-
152
- $start = ! empty( $args['start'] ) && $this->is_valid_date( $args['start'] ) ? $args['start'] : '';
153
- $end = ! empty( $args['end'] ) && $this->is_valid_date( $args['end'] ) ? $args['end'] : '';
154
-
155
- if ( ! MonsterInsights()->license->license_can( $this->level ) ) {
156
- return array(
157
- 'success' => true,
158
- 'upgrade' => true,
159
- 'data' => array(),
160
- );
161
- }
162
-
163
- if ( ! $this->is_valid_date_range( $start, $end ) ) {
164
- return array(
165
- 'success' => false,
166
- 'error' => __( 'Invalid date range.', 'google-analytics-for-wordpress' ),
167
- 'data' => array(),
168
- );
169
- }
170
-
171
- if ( ( $start !== $this->default_start_date() || $end !== $this->default_end_date() ) && ! monsterinsights_is_pro_version() ) {
172
- $start = $this->default_start_date();
173
- $end = $this->default_end_date();
174
- // return array(
175
- // 'success' => false,
176
- // 'error' => __( 'Please upgrade to MonsterInsights Pro to use custom date ranges.', 'google-analytics-for-wordpress' ),
177
- // 'data' => array(),
178
- // );
179
- }
180
-
181
- $error = apply_filters( 'monsterinsights_reports_abstract_get_data_pre_cache', false, $args, $this->name );
182
- if ( $error ) {
183
- return apply_filters( 'monsterinsights_reports_handle_error_message', array(
184
- 'success' => false,
185
- 'error' => $error,
186
- 'data' => array(),
187
- ) );
188
- }
189
-
190
- $check_cache = ( $start === $this->default_start_date() && $end === $this->default_end_date() ) || apply_filters( 'monsterinsights_report_use_cache', false, $this->name );
191
- $site_auth = MonsterInsights()->auth->get_viewname();
192
- $ms_auth = is_multisite() && MonsterInsights()->auth->get_network_viewname();
193
- $transient = 'monsterinsights_report_' . $this->name . '_' . $start . '_' . $end;
194
- // Set to same time as MI cache. MI caches same day to 15 and others to 1 day, so there's no point pinging MI before then.
195
- $expiration = $end === date( 'Y-m-d' ) ? apply_filters( 'monsterinsights_report_transient_expiration', 15 * MINUTE_IN_SECONDS, $this->name ) : DAY_IN_SECONDS;
196
-
197
- // Default date range, check
198
- if ( $site_auth || $ms_auth ) {
199
- // Single site or MS with auth at subsite
200
- $option_name = $site_auth ? 'monsterinsights_report_data_' . $this->name : 'monsterinsights_network_report_data_' . $this->name;
201
- $p = $site_auth ? MonsterInsights()->auth->get_viewid() : MonsterInsights()->auth->get_network_viewid();
202
-
203
- $data = array();
204
- if ( $check_cache ) {
205
- $data = ! $site_auth && $ms_auth ? get_site_option( $option_name, array() ) : get_option( $option_name, array() );
206
- } else {
207
- $data = ! $site_auth && $ms_auth ? get_site_transient( $transient ) : get_transient( $transient );
208
- }
209
-
210
- if ( ! empty( $data ) &&
211
- ! empty( $data['expires'] ) &&
212
- $data['expires'] >= time() &&
213
- ! empty( $data['data'] ) &&
214
- ! empty( $data['p'] ) &&
215
- $data['p'] === $p
216
- ) {
217
- return array(
218
- 'success' => true,
219
- 'data' => $data['data'],
220
- );
221
- }
222
-
223
- // Nothing in cache, either not saved before, expired or mismatch. Let's grab from API
224
- $api_options = array( 'start' => $start, 'end' => $end );
225
- if ( ! $site_auth && $ms_auth ) {
226
- $api_options['network'] = true;
227
- }
228
-
229
- $api = new MonsterInsights_API_Request( 'analytics/reports/' . $this->name . '/', $api_options, 'GET' );
230
-
231
- $additional_data = $this->additional_data();
232
-
233
- if ( ! empty( $additional_data ) ) {
234
- $api->set_additional_data( $additional_data );
235
- }
236
-
237
- $ret = $api->request();
238
-
239
- if ( is_wp_error( $ret ) ) {
240
- return array(
241
- 'success' => false,
242
- 'error' => $ret->get_error_message(),
243
- 'data' => array(),
244
- );
245
- } else {
246
- // Success
247
- $data = array(
248
- 'expires' => $expiration,
249
- 'p' => $p,
250
- 'data' => $ret['data'],
251
- );
252
- if ( $check_cache ) {
253
- ! $site_auth && $ms_auth ? update_site_option( $option_name, $data ) : update_option( $option_name, $data );
254
- } else {
255
- ! $site_auth && $ms_auth ? set_site_transient( $option_name, $data, $expiration ) : set_transient( $option_name, $data, $expiration );
256
- }
257
-
258
- return $this->prepare_report_data( array(
259
- 'success' => true,
260
- 'data' => $ret['data'],
261
- ) );
262
- }
263
-
264
- } else {
265
- return array(
266
- 'success' => false,
267
- 'error' => __( 'You must authenticate with MonsterInsights to use reports.', 'google-analytics-for-wordpress' ),
268
- 'data' => array(),
269
- );
270
- }
271
- }
272
-
273
- public function default_start_date() {
274
- return date( 'Y-m-d', strtotime( '-30 days' ) );
275
- }
276
-
277
- public function default_end_date() {
278
- return date( 'Y-m-d', strtotime( '-1 day' ) );
279
- }
280
-
281
- // Checks to see if date range is valid. Should be 30-yesterday always for lite & any valid date range to today for Pro.
282
- public function is_valid_date_range( $start, $end ) {
283
- $start = strtotime( $start );
284
- $end = strtotime( $end );
285
-
286
- if ( $start > strtotime( 'now' ) || $end > strtotime( 'now' ) || $start < strtotime( '01 January 2005' ) || $end < strtotime( '01 January 2005' ) ) {
287
- return false;
288
- }
289
-
290
- // return false if the start date is after the end date
291
- return ( $start > $end ) ? false : true;
292
- }
293
-
294
- // Is a valid date value
295
- public function is_valid_date( $date = '' ) {
296
- $d = MonsterInsightsDateTime::createFromFormat( 'Y-m-d', $date );
297
-
298
- return $d && $d->format( 'Y-m-d' ) === $date;
299
- }
300
-
301
- /**
302
- * Do not use the functions below this. They are unused and are just here so people
303
- * with out of date MonsterInsights addons won't get fatal errors.
304
- */
305
- protected function get_api_max_limit() {
306
- return 300;
307
- }
308
-
309
- protected function get_date_range() {
310
- return array();
311
- }
312
-
313
- public function get_upsell_notice() {
314
- $has_level = MonsterInsights()->license->get_license_type();
315
- $has_level = $has_level ? $has_level : 'lite';
316
- $message = sprintf( __( 'You currently have a %s level license, but this report requires at least a %s level license to view the %s. Please upgrade to view this report.', 'google-analytics-for-wordpress' ), $has_level, $this->level, $this->title );
317
- ob_start(); ?>
318
- <div class="monsterinsights-upsell-report-container monsterinsights-upsell-report-<?php echo $this->name; ?>-bg">
319
- <div class="monsterinsights-upsell-container">
320
- <div class="row justify-content-center">
321
- <div class="col-lg-10 col-lg-offset-1 align-self-center">
322
- <div class="monsterinsights-upsell-card">
323
- <img class="monsterinsights-upgrade-mascot"
324
- src="<?php echo trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ); ?>assets/css/images/mascot.png"
325
- srcset="<?php echo trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ); ?>assets/css/images/mascot@2x.png 2x"
326
- alt="">
327
- <div class="monsterinsights-upsell-card-card-content">
328
- <span class="monsterinsights-upsell-card-title"><?php esc_html_e( 'Ready to Get Analytics Super-Powers?', 'google-analytics-for-wordpress' ); ?></span>
329
- <p class="monsterinsights-upsell-card-subtitle">
330
- <strong><?php esc_html_e( '(And Crush Your Competition?)', 'google-analytics-for-wordpress' ); ?></strong>
331
- </p> &nbsp;
332
- <?php if ( monsterinsights_is_pro_version() ) { ?>
333
- <p><?php echo sprintf( esc_html__( "Hey there! It looks like you've got the %s license installed on your site.
334
- That's awesome! %s", 'google-analytics-for-wordpress' ), $has_level, '<span class="dashicons dashicons-smiley"></span>' ); ?></p>
335
- &nbsp;
336
- <p><?php echo sprintf( esc_html__( "Do you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with the %s level%s of our paid packages. You'll need to upgrade your license to get instant access.", 'google-analytics-for-wordpress' ), '<strong>' . $this->title, '</strong>', '<strong><a href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://monsterinsights.com/my-account/' ) . '">' . $this->level, '</a></strong>' ); ?></p>
337
- &nbsp;
338
- <p><?php echo sprintf( esc_html__( "It's easy! To upgrade, navigate to %sMy Account%s on MonsterInsights.com, go to the licenses tab, and click upgrade. We also have a %sstep by step guide%s with pictures of this process.", 'google-analytics-for-wordpress' ), '<a href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://monsterinsights.com/my-account/' ) . '"><strong>', '</strong></a>', '<a href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://www.monsterinsights.com/docs/upgrade-monsterinsights-license/' ) . '" style="text-decoration:underline !important">', '</a>' ); ?></p>
339
- &nbsp;
340
- <p><?php esc_html_e( "If you have any questions, don't hesitate to reach out. We're here to help.", 'google-analytics-for-wordpress' ); ?></p>
341
- <?php } else { ?>
342
- <p><?php echo sprintf( esc_html__( "Hey there! %s It looks like you've got the free version of MonsterInsights installed on your site.
343
- That's awesome!", 'google-analytics-for-wordpress' ), '<span class="dashicons dashicons-smiley"></span>' ); ?></p>
344
- &nbsp;
345
- <p><?php echo sprintf( esc_html__( "Do you you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with %s level%s of our paid packages. To get instant access, you'll want to buy a MonsterInsights license, which also gives you access to powerful addons, expanded reporting (including the ability to use custom date ranges), comprehensive tracking features (like UserID tracking) and access to our world-class support team.", 'google-analytics-for-wordpress' ), '<strong>' . $this->title, '</strong>', '<a href="' . monsterinsights_get_upgrade_link( 'reports-page', $this->name . '-report-upsell-license-link' ) . '">' . $this->level, '</a>' ); ?></p>
346
- &nbsp;
347
- <p><?php echo sprintf( esc_html__( "Upgrading is easy! To upgrade, navigate to %sour pricing page%s, purchase the required license, and then follow the %sinstructions in the email receipt%s to upgrade. It only takes a few minutes to unlock the most powerful, yet easy to use analytics tracking system for WordPress.", 'google-analytics-for-wordpress' ), '<a href="' . monsterinsights_get_upgrade_link( 'reports-page', $this->name . '-report-upsell-license-link' ) . '"><strong>', '</strong></a>', '<a style="text-decoration:underline !important" href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-go-lite-pro-link', 'https://www.monsterinsights.com/docs/go-lite-pro/' ) . '">', '</a>' ); ?></p>
348
- &nbsp;
349
- <p><?php esc_html_e( "If you have any questions, don't hesitate to reach out. We're here to help.", 'google-analytics-for-wordpress' ); ?></p>
350
- <?php } ?>
351
- </div>
352
- <div class="monsterinsights-upsell-card-action">
353
- <?php if ( monsterinsights_is_pro_version() ) { ?>
354
- <a href="<?php echo monsterinsights_get_upgrade_link( 'reports-page', $this->name . '-report-upsell-license-link' ); ?>"
355
- class="monsterinsights-upsell-card-button"><?php esc_html_e( 'Upgrade Now', 'google-analytics-for-wordpress' ); ?></a>
356
- <?php } else { ?>
357
- <a href="<?php echo monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://www.monsterinsights.com/docs/upgrade-monsterinsights-license/' ); ?>"
358
- class="monsterinsights-upsell-card-button"><?php esc_html_e( 'Get MonsterInsights Pro', 'google-analytics-for-wordpress' ); ?></a>
359
- <?php } ?>
360
- </div>
361
- </div>
362
- </div>
363
- </div>
364
- </div>
365
- </div>
366
- </div>
367
- <?php
368
- return ob_get_clean();
369
- }
370
-
371
- function get_ga_report_range( $data = array() ) {
372
- if ( empty( $data['reportcurrentrange'] ) || empty( $data['reportcurrentrange']['startDate'] ) || empty( $data['reportcurrentrange']['endDate'] ) ) {
373
- return '';
374
- } else {
375
- if ( ! empty( $data['reportprevrange'] ) && ! empty( $data['reportprevrange']['startDate'] ) && ! empty( $data['reportprevrange']['endDate'] ) ) {
376
- return urlencode( '_u.date00=' . str_replace( '-', '', $data['reportcurrentrange']['startDate'] ) . '&_u.date01=' . str_replace( '-', '', $data['reportcurrentrange']['endDate'] ) . '&_u.date10=' . str_replace( '-', '', $data['reportprevrange']['startDate'] ) . '&_u.date11=' . str_replace( '-', '', $data['reportprevrange']['endDate'] ) );
377
- } else {
378
- return urlencode( '_u.date00=' . str_replace( '-', '', $data['reportcurrentrange']['startDate'] ) . '&_u.date01=' . str_replace( '-', '', $data['reportcurrentrange']['endDate'] ) );
379
- }
380
- }
381
- }
382
-
383
- /**
384
- * Grab the link to the addons page used in each report's error message.
385
- *
386
- * @return string
387
- */
388
- public function get_addons_page_link() {
389
- if ( current_user_can( 'install_plugins' ) ) {
390
- $addons_url = is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' );
391
- $addons_link = sprintf( '<a href="%1$s">%2$s</a>', $addons_url, esc_html__( 'Visit addons page', 'google-analytics-for-wordpress' ) );
392
- } else {
393
- $addons_link = esc_html__( 'Please ask your webmaster to enable this addon.', 'google-analytics-for-wordpress' );
394
- }
395
-
396
- return $addons_link;
397
- }
398
-
399
- /**
400
- * When called will add the footer link to be displayed in the error popup.
401
- *
402
- * @param array $data The data sent as error response to the ajax call.
403
- *
404
- * @return array
405
- */
406
- public function add_error_addon_link( $data ) {
407
- $data['data']['footer'] = $this->get_addons_page_link();
408
-
409
- return $data;
410
- }
411
-
412
- /**
413
- * Added to allow individual reports to alter data when outputting for Vue reports.
414
- *
415
- * @param $data
416
- *
417
- * @return mixed
418
- */
419
- public function prepare_report_data( $data ) {
420
- return $data;
421
- }
422
- }
423
-
424
- if ( ! class_exists( 'MonsterInsightsDateTime' ) ) {
425
- class MonsterInsightsDateTime extends DateTime {
426
- public static function createFromFormat( $format, $time, $timezone = null ) {
427
- if ( ! $timezone ) {
428
- $timezone = new DateTimeZone( date_default_timezone_get() );
429
- }
430
- if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) {
431
- return parent::createFromFormat( $format, $time, $timezone );
432
- }
433
-
434
- return new DateTime( date( $format, strtotime( $time ) ), $timezone );
435
- }
436
- }
437
- }
 
 
1
+ <?php
2
+ /**
3
+ * Report Abstract
4
+ *
5
+ * Ensures all of the reports have a uniform class with helper functions.
6
+ *
7
+ * @since 6.0.0
8
+ *
9
+ * @package MonsterInsights
10
+ * @subpackage Reports
11
+ * @author Chris Christoff
12
+ */
13
+
14
+ // Exit if accessed directly
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit;
17
+ }
18
+
19
+ class MonsterInsights_Report {
20
+
21
+ public $title;
22
+ public $class;
23
+ public $name;
24
+ public $version = '1.0.0';
25
+
26
+ /**
27
+ * Primary class constructor.
28
+ *
29
+ * @access public
30
+ * @since 6.0.0
31
+ */
32
+ public function __construct() {
33
+ add_filter( 'monsterinsights_reports_abstract_get_data_pre_cache', array( $this, 'requirements' ), 10, 3 );
34
+ }
35
+
36
+ // Let's get the HTML to output for a particular report. This is not the AJAX endpoint. Args can hold things (generally start/end date range)
37
+ protected function get_report_html( $args = array() ) {
38
+ /* Defined in the report class */
39
+ // For ajax, args start, end, and data will be set with the data to use. Else call $this->get_data( array( 'default' => true ) )
40
+ return '';
41
+ }
42
+
43
+ public function additional_data() {
44
+ return array();
45
+ }
46
+
47
+ public function requirements( $error = false, $args = array(), $name = '' ) {
48
+ return $error;
49
+ }
50
+
51
+ public function show_report( $args = array() ) {
52
+
53
+ if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
54
+ return monsterinsights_get_message( 'error', esc_html__( 'Access denied', 'google-analytics-for-wordpress' ) );
55
+ }
56
+
57
+ if ( monsterinsights_get_option( 'dashboard_disabled', false ) ) {
58
+ if ( current_user_can( 'monsterinsights_save_settings' ) ) {
59
+ $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
60
+
61
+ return monsterinsights_get_message( 'error',
62
+ sprintf(
63
+ esc_html__( 'Please %1$senable the dashboard%2$s to see report data.', 'google-analytics-for-wordpress' ),
64
+ '<a href="' . $url . '">',
65
+ '</a>'
66
+ )
67
+ );
68
+ } else {
69
+ return monsterinsights_get_message( 'error', esc_html__( 'The dashboard is disabled.', 'google-analytics-for-wordpress' ) );
70
+ }
71
+ }
72
+
73
+ if ( monsterinsights_is_pro_version() ) {
74
+ if ( ! MonsterInsights()->license->has_license() ) {
75
+ $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
76
+
77
+ return monsterinsights_get_message( 'error', esc_html__( 'You do not have an active license. Please %1$scheck your license configuration.%2$s', 'google-analytics-for-wordpress' ), '<a href="' . $url . '">', '</a>' );
78
+ } else if ( MonsterInsights()->license->license_has_error() ) {
79
+ return monsterinsights_get_message( 'error', $this->get_license_error() );
80
+ }
81
+ }
82
+
83
+ if ( ! ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() ) ) {
84
+ if ( current_user_can( 'monsterinsights_save_settings' ) ) {
85
+ $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' );
86
+
87
+ return monsterinsights_get_message( 'error',
88
+ sprintf(
89
+ esc_html__( 'Please %1$sauthenticate %2$swith Google Analytics to allow the plugin to fetch data.', 'google-analytics-for-wordpress' ),
90
+ '<a href="' . $url . '">',
91
+ '</a>'
92
+ )
93
+ );
94
+ } else {
95
+ return monsterinsights_get_message( 'error', esc_html__( 'The Google oAuth authentication needs to be re-authenticated to view data.', 'google-analytics-for-wordpress' ) );
96
+ }
97
+ }
98
+
99
+ if ( monsterinsights_is_pro_version() ) {
100
+ if ( ! MonsterInsights()->license->license_can( $this->level ) ) {
101
+ return $this->get_upsell_notice();
102
+ }
103
+ }
104
+
105
+ $error = $this->requirements( false, array(), $this->name );
106
+
107
+ if ( ! empty( $error ) ) {
108
+ return monsterinsights_get_message( 'error', $error );
109
+ }
110
+
111
+ if ( ! empty( $args['error'] ) ) {
112
+ return monsterinsights_get_message( 'error', $args['error'] );
113
+ }
114
+
115
+ if ( empty( $args['data'] ) || ! is_array( $args['data'] ) ) {
116
+ if ( monsterinsights_is_pro_version() ) {
117
+ return '';
118
+ } else {
119
+ // Try to get default data.
120
+ $args = $this->get_data( array( 'default' => true ) );
121
+ if ( empty( $args['data'] ) || is_array( $args['data'] ) ) {
122
+ return monsterinsights_get_message( 'error', __( 'No data found', 'google-analytics-for-wordpress' ) );
123
+ }
124
+
125
+ if ( ! empty( $args['error'] ) ) {
126
+ return monsterinsights_get_message( 'error', $data['error'] );
127
+ }
128
+ }
129
+ }
130
+
131
+ return $this->get_report_html( $args['data'] );
132
+ }
133
+
134
+ // Deletes the report data from the cache
135
+ public function delete_cache( $where = 'site' ) {
136
+
137
+ if ( $where === 'site' || $where === 'both' ) {
138
+ delete_option( 'monsterinsights_report_data_' . $this->name );
139
+ }
140
+
141
+ if ( $where === 'network' || $where === 'both' ) {
142
+ delete_option( 'monsterinsights_network_report_data_' . $this->name );
143
+ }
144
+ }
145
+
146
+ // Get report data
147
+ public function get_data( $args = array() ) {
148
+
149
+ if ( ! empty( $args['default'] ) ) {
150
+ $args['start'] = $this->default_start_date();
151
+ $args['end'] = $this->default_end_date();
152
+ }
153
+
154
+ $start = ! empty( $args['start'] ) && $this->is_valid_date( $args['start'] ) ? $args['start'] : '';
155
+ $end = ! empty( $args['end'] ) && $this->is_valid_date( $args['end'] ) ? $args['end'] : '';
156
+
157
+ if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $this->level ) ) {
158
+ return array(
159
+ 'success' => true,
160
+ 'upgrade' => true,
161
+ 'data' => array(),
162
+ );
163
+ }
164
+
165
+ if ( ! $this->is_valid_date_range( $start, $end ) ) {
166
+ return array(
167
+ 'success' => false,
168
+ 'error' => __( 'Invalid date range.', 'google-analytics-for-wordpress' ),
169
+ 'data' => array(),
170
+ );
171
+ }
172
+
173
+ if ( ( $start !== $this->default_start_date() || $end !== $this->default_end_date() ) && ! monsterinsights_is_pro_version() ) {
174
+ $start = $this->default_start_date();
175
+ $end = $this->default_end_date();
176
+ // return array(
177
+ // 'success' => false,
178
+ // 'error' => __( 'Please upgrade to MonsterInsights Pro to use custom date ranges.', 'google-analytics-for-wordpress' ),
179
+ // 'data' => array(),
180
+ // );
181
+ }
182
+
183
+ $error = apply_filters( 'monsterinsights_reports_abstract_get_data_pre_cache', false, $args, $this->name );
184
+ if ( $error ) {
185
+ return apply_filters( 'monsterinsights_reports_handle_error_message', array(
186
+ 'success' => false,
187
+ 'error' => $error,
188
+ 'data' => array(),
189
+ ) );
190
+ }
191
+
192
+ $check_cache = ( $start === $this->default_start_date() && $end === $this->default_end_date() ) || apply_filters( 'monsterinsights_report_use_cache', false, $this->name );
193
+ $site_auth = MonsterInsights()->auth->get_viewname();
194
+ $ms_auth = is_multisite() && MonsterInsights()->auth->get_network_viewname();
195
+ $transient = 'monsterinsights_report_' . $this->name . '_' . $start . '_' . $end;
196
+ // Set to same time as MI cache. MI caches same day to 15 and others to 1 day, so there's no point pinging MI before then.
197
+ $expiration = $end === date( 'Y-m-d' ) ? apply_filters( 'monsterinsights_report_transient_expiration', 15 * MINUTE_IN_SECONDS, $this->name ) : DAY_IN_SECONDS;
198
+
199
+ // Default date range, check
200
+ if ( $site_auth || $ms_auth ) {
201
+ // Single site or MS with auth at subsite
202
+ $option_name = $site_auth ? 'monsterinsights_report_data_' . $this->name : 'monsterinsights_network_report_data_' . $this->name;
203
+ $p = $site_auth ? MonsterInsights()->auth->get_viewid() : MonsterInsights()->auth->get_network_viewid();
204
+
205
+ $data = array();
206
+ if ( $check_cache ) {
207
+ $data = ! $site_auth && $ms_auth ? get_site_option( $option_name, array() ) : get_option( $option_name, array() );
208
+ } else {
209
+ $data = ! $site_auth && $ms_auth ? get_site_transient( $transient ) : get_transient( $transient );
210
+ }
211
+
212
+ if ( ! empty( $data ) &&
213
+ ! empty( $data['expires'] ) &&
214
+ $data['expires'] >= time() &&
215
+ ! empty( $data['data'] ) &&
216
+ ! empty( $data['p'] ) &&
217
+ $data['p'] === $p
218
+ ) {
219
+ return array(
220
+ 'success' => true,
221
+ 'data' => $data['data'],
222
+ );
223
+ }
224
+
225
+ // Nothing in cache, either not saved before, expired or mismatch. Let's grab from API
226
+ $api_options = array( 'start' => $start, 'end' => $end );
227
+ if ( ! $site_auth && $ms_auth ) {
228
+ $api_options['network'] = true;
229
+ }
230
+
231
+ $api = new MonsterInsights_API_Request( 'analytics/reports/' . $this->name . '/', $api_options, 'GET' );
232
+
233
+ $additional_data = $this->additional_data();
234
+
235
+ if ( ! empty( $additional_data ) ) {
236
+ $api->set_additional_data( $additional_data );
237
+ }
238
+
239
+ $ret = $api->request();
240
+
241
+ if ( is_wp_error( $ret ) ) {
242
+ return array(
243
+ 'success' => false,
244
+ 'error' => $ret->get_error_message(),
245
+ 'data' => array(),
246
+ );
247
+ } else {
248
+ // Success
249
+ $data = array(
250
+ 'expires' => $expiration,
251
+ 'p' => $p,
252
+ 'data' => $ret['data'],
253
+ );
254
+ if ( $check_cache ) {
255
+ ! $site_auth && $ms_auth ? update_site_option( $option_name, $data ) : update_option( $option_name, $data );
256
+ } else {
257
+ ! $site_auth && $ms_auth ? set_site_transient( $option_name, $data, $expiration ) : set_transient( $option_name, $data, $expiration );
258
+ }
259
+
260
+ return $this->prepare_report_data( array(
261
+ 'success' => true,
262
+ 'data' => $ret['data'],
263
+ ) );
264
+ }
265
+
266
+ } else {
267
+ return array(
268
+ 'success' => false,
269
+ 'error' => __( 'You must authenticate with MonsterInsights to use reports.', 'google-analytics-for-wordpress' ),
270
+ 'data' => array(),
271
+ );
272
+ }
273
+ }
274
+
275
+ public function default_start_date() {
276
+ return date( 'Y-m-d', strtotime( '-30 days' ) );
277
+ }
278
+
279
+ public function default_end_date() {
280
+ return date( 'Y-m-d', strtotime( '-1 day' ) );
281
+ }
282
+
283
+ // Checks to see if date range is valid. Should be 30-yesterday always for lite & any valid date range to today for Pro.
284
+ public function is_valid_date_range( $start, $end ) {
285
+ $start = strtotime( $start );
286
+ $end = strtotime( $end );
287
+
288
+ if ( $start > strtotime( 'now' ) || $end > strtotime( 'now' ) || $start < strtotime( '01 January 2005' ) || $end < strtotime( '01 January 2005' ) ) {
289
+ return false;
290
+ }
291
+
292
+ // return false if the start date is after the end date
293
+ return ( $start > $end ) ? false : true;
294
+ }
295
+
296
+ // Is a valid date value
297
+ public function is_valid_date( $date = '' ) {
298
+ $d = MonsterInsightsDateTime::createFromFormat( 'Y-m-d', $date );
299
+
300
+ return $d && $d->format( 'Y-m-d' ) === $date;
301
+ }
302
+
303
+ /**
304
+ * Do not use the functions below this. They are unused and are just here so people
305
+ * with out of date MonsterInsights addons won't get fatal errors.
306
+ */
307
+ protected function get_api_max_limit() {
308
+ return 300;
309
+ }
310
+
311
+ protected function get_date_range() {
312
+ return array();
313
+ }
314
+
315
+ public function get_upsell_notice() {
316
+ $has_level = monsterinsights_is_pro_version() ? MonsterInsights()->license->get_license_type() : false;
317
+ $has_level = $has_level ? $has_level : 'lite';
318
+ $message = sprintf( __( 'You currently have a %s level license, but this report requires at least a %s level license to view the %s. Please upgrade to view this report.', 'google-analytics-for-wordpress' ), $has_level, $this->level, $this->title );
319
+ ob_start(); ?>
320
+ <div class="monsterinsights-upsell-report-container monsterinsights-upsell-report-<?php echo $this->name; ?>-bg">
321
+ <div class="monsterinsights-upsell-container">
322
+ <div class="row justify-content-center">
323
+ <div class="col-lg-10 col-lg-offset-1 align-self-center">
324
+ <div class="monsterinsights-upsell-card">
325
+ <img class="monsterinsights-upgrade-mascot"
326
+ src="<?php echo trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ); ?>assets/css/images/mascot.png"
327
+ srcset="<?php echo trailingslashit( MONSTERINSIGHTS_PLUGIN_URL ); ?>assets/css/images/mascot@2x.png 2x"
328
+ alt="">
329
+ <div class="monsterinsights-upsell-card-card-content">
330
+ <span class="monsterinsights-upsell-card-title"><?php esc_html_e( 'Ready to Get Analytics Super-Powers?', 'google-analytics-for-wordpress' ); ?></span>
331
+ <p class="monsterinsights-upsell-card-subtitle">
332
+ <strong><?php esc_html_e( '(And Crush Your Competition?)', 'google-analytics-for-wordpress' ); ?></strong>
333
+ </p> &nbsp;
334
+ <?php if ( monsterinsights_is_pro_version() ) { ?>
335
+ <p><?php echo sprintf( esc_html__( "Hey there! It looks like you've got the %s license installed on your site.
336
+ That's awesome! %s", 'google-analytics-for-wordpress' ), $has_level, '<span class="dashicons dashicons-smiley"></span>' ); ?></p>
337
+ &nbsp;
338
+ <p><?php echo sprintf( esc_html__( "Do you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with the %s level%s of our paid packages. You'll need to upgrade your license to get instant access.", 'google-analytics-for-wordpress' ), '<strong>' . $this->title, '</strong>', '<strong><a href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://monsterinsights.com/my-account/' ) . '">' . $this->level, '</a></strong>' ); ?></p>
339
+ &nbsp;
340
+ <p><?php echo sprintf( esc_html__( "It's easy! To upgrade, navigate to %sMy Account%s on MonsterInsights.com, go to the licenses tab, and click upgrade. We also have a %sstep by step guide%s with pictures of this process.", 'google-analytics-for-wordpress' ), '<a href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://monsterinsights.com/my-account/' ) . '"><strong>', '</strong></a>', '<a href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://www.monsterinsights.com/docs/upgrade-monsterinsights-license/' ) . '" style="text-decoration:underline !important">', '</a>' ); ?></p>
341
+ &nbsp;
342
+ <p><?php esc_html_e( "If you have any questions, don't hesitate to reach out. We're here to help.", 'google-analytics-for-wordpress' ); ?></p>
343
+ <?php } else { ?>
344
+ <p><?php echo sprintf( esc_html__( "Hey there! %s It looks like you've got the free version of MonsterInsights installed on your site.
345
+ That's awesome!", 'google-analytics-for-wordpress' ), '<span class="dashicons dashicons-smiley"></span>' ); ?></p>
346
+ &nbsp;
347
+ <p><?php echo sprintf( esc_html__( "Do you you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with %s level%s of our paid packages. To get instant access, you'll want to buy a MonsterInsights license, which also gives you access to powerful addons, expanded reporting (including the ability to use custom date ranges), comprehensive tracking features (like UserID tracking) and access to our world-class support team.", 'google-analytics-for-wordpress' ), '<strong>' . $this->title, '</strong>', '<a href="' . monsterinsights_get_upgrade_link( 'reports-page', $this->name . '-report-upsell-license-link' ) . '">' . $this->level, '</a>' ); ?></p>
348
+ &nbsp;
349
+ <p><?php echo sprintf( esc_html__( "Upgrading is easy! To upgrade, navigate to %sour pricing page%s, purchase the required license, and then follow the %sinstructions in the email receipt%s to upgrade. It only takes a few minutes to unlock the most powerful, yet easy to use analytics tracking system for WordPress.", 'google-analytics-for-wordpress' ), '<a href="' . monsterinsights_get_upgrade_link( 'reports-page', $this->name . '-report-upsell-license-link' ) . '"><strong>', '</strong></a>', '<a style="text-decoration:underline !important" href="' . monsterinsights_get_url( 'reports-page', $this->name . '-report-go-lite-pro-link', 'https://www.monsterinsights.com/docs/go-lite-pro/' ) . '">', '</a>' ); ?></p>
350
+ &nbsp;
351
+ <p><?php esc_html_e( "If you have any questions, don't hesitate to reach out. We're here to help.", 'google-analytics-for-wordpress' ); ?></p>
352
+ <?php } ?>
353
+ </div>
354
+ <div class="monsterinsights-upsell-card-action">
355
+ <?php if ( monsterinsights_is_pro_version() ) { ?>
356
+ <a href="<?php echo monsterinsights_get_upgrade_link( 'reports-page', $this->name . '-report-upsell-license-link' ); ?>"
357
+ class="monsterinsights-upsell-card-button"><?php esc_html_e( 'Upgrade Now', 'google-analytics-for-wordpress' ); ?></a>
358
+ <?php } else { ?>
359
+ <a href="<?php echo monsterinsights_get_url( 'reports-page', $this->name . '-report-upsell-license-link', 'https://www.monsterinsights.com/docs/upgrade-monsterinsights-license/' ); ?>"
360
+ class="monsterinsights-upsell-card-button"><?php esc_html_e( 'Get MonsterInsights Pro', 'google-analytics-for-wordpress' ); ?></a>
361
+ <?php } ?>
362
+ </div>
363
+ </div>
364
+ </div>
365
+ </div>
366
+ </div>
367
+ </div>
368
+ </div>
369
+ <?php
370
+ return ob_get_clean();
371
+ }
372
+
373
+ function get_ga_report_range( $data = array() ) {
374
+ if ( empty( $data['reportcurrentrange'] ) || empty( $data['reportcurrentrange']['startDate'] ) || empty( $data['reportcurrentrange']['endDate'] ) ) {
375
+ return '';
376
+ } else {
377
+ if ( ! empty( $data['reportprevrange'] ) && ! empty( $data['reportprevrange']['startDate'] ) && ! empty( $data['reportprevrange']['endDate'] ) ) {
378
+ return urlencode( '_u.date00=' . str_replace( '-', '', $data['reportcurrentrange']['startDate'] ) . '&_u.date01=' . str_replace( '-', '', $data['reportcurrentrange']['endDate'] ) . '&_u.date10=' . str_replace( '-', '', $data['reportprevrange']['startDate'] ) . '&_u.date11=' . str_replace( '-', '', $data['reportprevrange']['endDate'] ) );
379
+ } else {
380
+ return urlencode( '_u.date00=' . str_replace( '-', '', $data['reportcurrentrange']['startDate'] ) . '&_u.date01=' . str_replace( '-', '', $data['reportcurrentrange']['endDate'] ) );
381
+ }
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Grab the link to the addons page used in each report's error message.
387
+ *
388
+ * @return string
389
+ */
390
+ public function get_addons_page_link() {
391
+ if ( current_user_can( 'install_plugins' ) ) {
392
+ $addons_url = is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' );
393
+ $addons_link = sprintf( '<a href="%1$s">%2$s</a>', $addons_url, esc_html__( 'Visit addons page', 'google-analytics-for-wordpress' ) );
394
+ } else {
395
+ $addons_link = esc_html__( 'Please ask your webmaster to enable this addon.', 'google-analytics-for-wordpress' );
396
+ }
397
+
398
+ return $addons_link;
399
+ }
400
+
401
+ /**
402
+ * When called will add the footer link to be displayed in the error popup.
403
+ *
404
+ * @param array $data The data sent as error response to the ajax call.
405
+ *
406
+ * @return array
407
+ */
408
+ public function add_error_addon_link( $data ) {
409
+ $data['data']['footer'] = $this->get_addons_page_link();
410
+
411
+ return $data;
412
+ }
413
+
414
+ /**
415
+ * Added to allow individual reports to alter data when outputting for Vue reports.
416
+ *
417
+ * @param $data
418
+ *
419
+ * @return mixed
420
+ */
421
+ public function prepare_report_data( $data ) {
422
+ return $data;
423
+ }
424
+ }
425
+
426
+ if ( ! class_exists( 'MonsterInsightsDateTime' ) ) {
427
+ class MonsterInsightsDateTime extends DateTime {
428
+ public static function createFromFormat( $format, $time, $timezone = null ) {
429
+ if ( ! $timezone ) {
430
+ $timezone = new DateTimeZone( date_default_timezone_get() );
431
+ }
432
+ if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) {
433
+ return parent::createFromFormat( $format, $time, $timezone );
434
+ }
435
+
436
+ return new DateTime( date( $format, strtotime( $time ) ), $timezone );
437
+ }
438
+ }
439
+ }
includes/admin/reports/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
includes/admin/reports/overview.php CHANGED
@@ -1,80 +1,80 @@
1
- <?php
2
- /**
3
- * Overview Report
4
- *
5
- * Ensures all of the reports have a uniform class with helper functions.
6
- *
7
- * @since 6.0.0
8
- *
9
- * @package MonsterInsights
10
- * @subpackage Reports
11
- * @author Chris Christoff
12
- */
13
-
14
- // Exit if accessed directly
15
- if ( ! defined( 'ABSPATH' ) ) {
16
- exit;
17
- }
18
-
19
- final class MonsterInsights_Report_Overview extends MonsterInsights_Report {
20
-
21
- public $title;
22
- public $class = 'MonsterInsights_Report_Overview';
23
- public $name = 'overview';
24
- public $version = '1.0.0';
25
- public $level = 'lite';
26
-
27
- /**
28
- * Primary class constructor.
29
- *
30
- * @access public
31
- * @since 6.0.0
32
- */
33
- public function __construct() {
34
- $this->title = __( 'Overview', 'google-analytics-for-wordpress' );
35
- parent::__construct();
36
- }
37
-
38
- /**
39
- * Prepare report-specific data for output.
40
- *
41
- * @param array $data The data from the report before it gets sent to the frontend.
42
- *
43
- * @return mixed
44
- */
45
- public function prepare_report_data( $data ) {
46
- // Add flags to the countries report.
47
- if ( ! empty( $data['data']['countries'] ) ) {
48
- $country_names = monsterinsights_get_country_list( true );
49
- foreach ( $data['data']['countries'] as $key => $country ) {
50
- $data['data']['countries'][ $key ]['name'] = isset( $country_names[ $country['iso'] ] ) ? $country_names[ $country['iso'] ] : $country['iso'];
51
- }
52
- }
53
-
54
- // Escape urls for the top pages report.
55
- if ( ! empty( $data['data']['toppages'] ) ) {
56
- foreach ( $data['data']['toppages'] as $key => $page ) {
57
- $title = $data['data']['toppages'][ $key ]['title'];
58
- $url = '(not set)' === $title ? '' : esc_url( $data['data']['toppages'][ $key ]['hostname'] );
59
-
60
- $data['data']['toppages'][ $key ]['hostname'] = $url;
61
- }
62
- }
63
-
64
- // Bounce rate add symbol.
65
- if ( ! empty( $data['data']['infobox']['bounce']['value'] ) ) {
66
- $data['data']['infobox']['bounce']['value'] .= '%';
67
- }
68
-
69
- // Add GA links.
70
- if ( ! empty( $data['data'] ) ) {
71
- $data['data']['galinks'] = array(
72
- 'countries' => 'https://analytics.google.com/analytics/web/#report/visitors-geo/' . MonsterInsights()->auth->get_referral_url() . $this->get_ga_report_range( $data['data'] ),
73
- 'referrals' => 'https://analytics.google.com/analytics/web/#report/trafficsources-referrals/' . MonsterInsights()->auth->get_referral_url() . $this->get_ga_report_range( $data['data'] ),
74
- 'topposts' => 'https://analytics.google.com/analytics/web/#/report/content-pages/' . MonsterInsights()->auth->get_referral_url() . $this->get_ga_report_range( $data['data'] ),
75
- );
76
- }
77
-
78
- return $data;
79
- }
80
- }
1
+ <?php
2
+ /**
3
+ * Overview Report
4
+ *
5
+ * Ensures all of the reports have a uniform class with helper functions.
6
+ *
7
+ * @since 6.0.0
8
+ *
9
+ * @package MonsterInsights
10
+ * @subpackage Reports
11
+ * @author Chris Christoff
12
+ */
13
+
14
+ // Exit if accessed directly
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit;
17
+ }
18
+
19
+ final class MonsterInsights_Report_Overview extends MonsterInsights_Report {
20
+
21
+ public $title;
22
+ public $class = 'MonsterInsights_Report_Overview';
23
+ public $name = 'overview';
24
+ public $version = '1.0.0';
25
+ public $level = 'lite';
26
+
27
+ /**
28
+ * Primary class constructor.
29
+ *
30
+ * @access public
31
+ * @since 6.0.0
32
+ */
33
+ public function __construct() {
34
+ $this->title = __( 'Overview', 'google-analytics-for-wordpress' );
35
+ parent::__construct();
36
+ }
37
+
38
+ /**
39
+ * Prepare report-specific data for output.
40
+ *
41
+ * @param array $data The data from the report before it gets sent to the frontend.
42
+ *
43
+ * @return mixed
44
+ */
45
+ public function prepare_report_data( $data ) {
46
+ // Add flags to the countries report.
47
+ if ( ! empty( $data['data']['countries'] ) ) {
48
+ $country_names = monsterinsights_get_country_list( true );
49
+ foreach ( $data['data']['countries'] as $key => $country ) {
50
+ $data['data']['countries'][ $key ]['name'] = isset( $country_names[ $country['iso'] ] ) ? $country_names[ $country['iso'] ] : $country['iso'];
51
+ }
52
+ }
53
+
54
+ // Escape urls for the top pages report.
55
+ if ( ! empty( $data['data']['toppages'] ) ) {
56
+ foreach ( $data['data']['toppages'] as $key => $page ) {
57
+ $title = $data['data']['toppages'][ $key ]['title'];
58
+ $url = '(not set)' === $title ? '' : esc_url( $data['data']['toppages'][ $key ]['hostname'] );
59
+
60
+ $data['data']['toppages'][ $key ]['hostname'] = $url;
61
+ }
62
+ }
63
+
64
+ // Bounce rate add symbol.
65
+ if ( ! empty( $data['data']['infobox']['bounce']['value'] ) ) {
66
+ $data['data']['infobox']['bounce']['value'] .= '%';
67
+ }
68
+
69
+ // Add GA links.
70
+ if ( ! empty( $data['data'] ) ) {
71
+ $data['data']['galinks'] = array(
72
+ 'countries' => 'https://analytics.google.com/analytics/web/#report/visitors-geo/' . MonsterInsights()->auth->get_referral_url() . $this->get_ga_report_range( $data['data'] ),
73
+ 'referrals' => 'https://analytics.google.com/analytics/web/#report/trafficsources-referrals/' . MonsterInsights()->auth->get_referral_url() . $this->get_ga_report_range( $data['data'] ),
74
+ 'topposts' => 'https://analytics.google.com/analytics/web/#/report/content-pages/' . MonsterInsights()->auth->get_referral_url() . $this->get_ga_report_range( $data['data'] ),
75
+ );
76
+ }
77
+
78
+ return $data;
79
+ }
80
+ }
includes/admin/review.php CHANGED
@@ -1,163 +1,188 @@
1
- <?php
2
- /**
3
- * Ask for some love.
4
- *
5
- * @package MonsterInsights
6
- * @author MonsterInsights
7
- * @since 7.0.7
8
- * @license GPL-2.0+
9
- * @copyright Copyright (c) 2018, MonsterInsights LLC
10
- */
11
- class MonsterInsights_Review {
12
- /**
13
- * Primary class constructor.
14
- *
15
- * @since 7.0.7
16
- */
17
- public function __construct() {
18
- // Admin notice requesting review.
19
- add_action( 'admin_notices', array( $this, 'review_request' ) );
20
- add_action( 'wp_ajax_monsterinsights_review_dismiss', array( $this, 'review_dismiss' ) );
21
- }
22
- /**
23
- * Add admin notices as needed for reviews.
24
- *
25
- * @since 7.0.7
26
- */
27
- public function review_request() {
28
- // Only consider showing the review request to admin users.
29
- if ( ! is_super_admin() ) {
30
- return;
31
- }
32
-
33
- // If the user has opted out of product annoucement notifications, don't
34
- // display the review request.
35
- if ( monsterinsights_get_option( 'hide_am_notices', false ) || monsterinsights_get_option( 'network_hide_am_notices', false ) ) {
36
- return;
37
- }
38
- // Verify that we can do a check for reviews.
39
- $review = get_option( 'monsterinsights_review' );
40
- $time = time();
41
- $load = false;
42
-
43
- if ( ! $review ) {
44
- $review = array(
45
- 'time' => $time,
46
- 'dismissed' => false,
47
- );
48
- update_option( 'monsterinsights_review', $review );
49
- } else {
50
- // Check if it has been dismissed or not.
51
- if ( ( isset( $review['dismissed'] ) && ! $review['dismissed'] ) && ( isset( $review['time'] ) && ( ( $review['time'] + DAY_IN_SECONDS ) <= $time ) ) ) {
52
- $load = true;
53
- }
54
- }
55
-
56
- // If we cannot load, return early.
57
- if ( ! $load ) {
58
- return;
59
- }
60
-
61
- $this->review();
62
- }
63
-
64
- /**
65
- * Maybe show review request.
66
- *
67
- * @since 7.0.7
68
- */
69
- public function review() {
70
- // Fetch when plugin was initially installed.
71
- $activated = get_option( 'monsterinsights_over_time', array() );
72
- if ( ! empty( $activated['installed_date'] ) ) {
73
- // Only continue if plugin has been installed for at least 14 days.
74
- if ( ( $activated['installed_date'] + ( DAY_IN_SECONDS * 14 ) ) > time() ) {
75
- return;
76
- }
77
- } else {
78
- $data = array(
79
- 'installed_version' => MONSTERINSIGHTS_VERSION,
80
- 'installed_date' => time(),
81
- 'installed_pro' => monsterinsights_is_pro_version(),
82
- );
83
-
84
- update_option( 'monsterinsights_over_time', $data );
85
- return;
86
- }
87
- // Only proceed with displaying if the user is tracking.
88
- $ua_code = monsterinsights_get_ua_to_output();
89
- if ( empty( $ua_code ) ) {
90
- return;
91
- }
92
-
93
- $feedback_url = monsterinsights_get_url( 'review-notice', 'feedback', add_query_arg( 'wpf192157_24', untrailingslashit( home_url() ), 'https://www.monsterinsights.com/plugin-feedback/' ) );
94
- // We have a candidate! Output a review message.
95
- ?>
96
- <div class="notice notice-info is-dismissible monsterinsights-review-notice">
97
- <div class="monsterinsights-review-step monsterinsights-review-step-1">
98
- <p><?php esc_html_e( 'Are you enjoying MonsterInsights?', 'google-analytics-for-wordpress' ); ?></p>
99
- <p>
100
- <a href="#" class="monsterinsights-review-switch-step" data-step="3"><?php esc_html_e( 'Yes', 'google-analytics-for-wordpress' ); ?></a><br />
101
- <a href="#" class="monsterinsights-review-switch-step" data-step="2"><?php esc_html_e( 'Not Really', 'google-analytics-for-wordpress' ); ?></a>
102
- </p>
103
- </div>
104
- <div class="monsterinsights-review-step monsterinsights-review-step-2" style="display: none">
105
- <p><?php esc_html_e( 'We\'re sorry to hear you aren\'t enjoying MonsterInsights. We would love a chance to improve. Could you take a minute and let us know what we can do better?', 'google-analytics-for-wordpress' ); ?></p>
106
- <p>
107
- <a href="<?php echo esc_url( $feedback_url ); ?>" class="monsterinsights-dismiss-review-notice monsterinsights-review-out"><?php esc_html_e( 'Give Feedback', 'google-analytics-for-wordpress' ); ?></a><br>
108
- <a href="#" class="monsterinsights-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'No thanks', 'google-analytics-for-wordpress' ); ?></a>
109
- </p>
110
- </div>
111
- <div class="monsterinsights-review-step monsterinsights-review-step-3" style="display: none">
112
- <p><?php esc_html_e( 'That’s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'google-analytics-for-wordpress' ); ?></p>
113
- <p><strong><?php echo wp_kses( __( '~ Syed Balkhi<br>Co-Founder of MonsterInsights', 'google-analytics-for-wordpress' ), array( 'br' => array() ) ); ?></strong></p>
114
- <p>
115
- <a href="https://wordpress.org/support/plugin/google-analytics-for-wordpress/reviews/?filter=5#new-post" class="monsterinsights-dismiss-review-notice monsterinsights-review-out" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Ok, you deserve it', 'google-analytics-for-wordpress' ); ?></a><br>
116
- <a href="#" class="monsterinsights-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Nope, maybe later', 'google-analytics-for-wordpress' ); ?></a><br>
117
- <a href="#" class="monsterinsights-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'I already did', 'google-analytics-for-wordpress' ); ?></a>
118
- </p>
119
- </div>
120
- </div>
121
- <script type="text/javascript">
122
- jQuery( document ).ready( function ( $ ) {
123
- $( document ).on( 'click', '.monsterinsights-dismiss-review-notice, .monsterinsights-review-notice button', function ( event ) {
124
- if ( ! $( this ).hasClass( 'monsterinsights-review-out' ) ) {
125
- event.preventDefault();
126
- }
127
- $.post( ajaxurl, {
128
- action: 'monsterinsights_review_dismiss'
129
- } );
130
- $( '.monsterinsights-review-notice' ).remove();
131
- } );
132
-
133
- $( document ).on( 'click', '.monsterinsights-review-switch-step', function ( e ) {
134
- e.preventDefault();
135
- var target = $( this ).attr( 'data-step' );
136
- if ( target ) {
137
- var notice = $( this ).closest( '.monsterinsights-review-notice' );
138
- var review_step = notice.find( '.monsterinsights-review-step-' + target );
139
- if ( review_step.length > 0 ) {
140
- notice.find( '.monsterinsights-review-step:visible').fadeOut( function ( ) {
141
- review_step.fadeIn();
142
- });
143
- }
144
- }
145
- })
146
- } );
147
- </script>
148
- <?php
149
- }
150
- /**
151
- * Dismiss the review admin notice
152
- *
153
- * @since 7.0.7
154
- */
155
- public function review_dismiss() {
156
- $review = get_option( 'monsterinsights_review', array() );
157
- $review['time'] = time();
158
- $review['dismissed'] = true;
159
- update_option( 'monsterinsights_review', $review );
160
- die;
161
- }
162
- }
163
- new MonsterInsights_Review;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Ask for some love.
4
+ *
5
+ * @package MonsterInsights
6
+ * @author MonsterInsights
7
+ * @since 7.0.7
8
+ * @license GPL-2.0+
9
+ * @copyright Copyright (c) 2018, MonsterInsights LLC
10
+ */
11
+ class MonsterInsights_Review {
12
+ /**
13
+ * Primary class constructor.
14
+ *
15
+ * @since 7.0.7
16
+ */
17
+ public function __construct() {
18
+ // Admin notice requesting review.
19
+ add_action( 'admin_notices', array( $this, 'review_request' ) );
20
+ add_action( 'wp_ajax_monsterinsights_review_dismiss', array( $this, 'review_dismiss' ) );
21
+ }
22
+ /**
23
+ * Add admin notices as needed for reviews.
24
+ *
25
+ * @since 7.0.7
26
+ */
27
+ public function review_request() {
28
+ // Only consider showing the review request to admin users.
29
+ if ( ! is_super_admin() ) {
30
+ return;
31
+ }
32
+
33
+ // If the user has opted out of product annoucement notifications, don't
34
+ // display the review request.
35
+ if ( monsterinsights_get_option( 'hide_am_notices', false ) || monsterinsights_get_option( 'network_hide_am_notices', false ) ) {
36
+ return;
37
+ }
38
+ // Verify that we can do a check for reviews.
39
+ $review = get_option( 'monsterinsights_review' );
40
+ $time = time();
41
+ $load = false;
42
+
43
+ if ( ! $review ) {
44
+ $review = array(
45
+ 'time' => $time,
46
+ 'dismissed' => false,
47
+ );
48
+ update_option( 'monsterinsights_review', $review );
49
+ } else {
50
+ // Check if it has been dismissed or not.
51
+ if ( ( isset( $review['dismissed'] ) && ! $review['dismissed'] ) && ( isset( $review['time'] ) && ( ( $review['time'] + DAY_IN_SECONDS ) <= $time ) ) ) {
52
+ $load = true;
53
+ }
54
+ }
55
+
56
+ // If we cannot load, return early.
57
+ if ( ! $load ) {
58
+ return;
59
+ }
60
+
61
+ $this->review();
62
+ }
63
+
64
+ /**
65
+ * Maybe show review request.
66
+ *
67
+ * @since 7.0.7
68
+ */
69
+ public function review() {
70
+ // Fetch when plugin was initially installed.
71
+ $activated = get_option( 'monsterinsights_over_time', array() );
72
+ $ua_code = monsterinsights_get_ua();
73
+
74
+ if ( ! empty( $activated['connected_date'] ) ) {
75
+ // Only continue if plugin has been tracking for at least 14 days.
76
+ if ( ( $activated['connected_date'] + ( DAY_IN_SECONDS * 14 ) ) > time() ) {
77
+ return;
78
+ }
79
+ } else {
80
+ $data = array(
81
+ 'installed_version' => MONSTERINSIGHTS_VERSION,
82
+ 'installed_date' => time(),
83
+ 'installed_pro' => monsterinsights_is_pro_version(),
84
+ );
85
+ // If already has a UA code mark as connected now.
86
+ if ( ! empty( $ua_code ) ) {
87
+ $data['connected_date'] = time();
88
+ }
89
+
90
+ update_option( 'monsterinsights_over_time', $data );
91
+ return;
92
+ }
93
+
94
+ // Only proceed with displaying if the user is tracking.
95
+ if ( empty( $ua_code ) ) {
96
+ return;
97
+ }
98
+
99
+ $feedback_url = add_query_arg( array(
100
+ 'wpf192157_24' => untrailingslashit( home_url() ),
101
+ 'wpf192157_26' => monsterinsights_get_license_key(),
102
+ 'wpf192157_27' => monsterinsights_is_pro_version() ? 'pro' : 'lite',
103
+ 'wpf192157_28' => MONSTERINSIGHTS_VERSION,
104
+ ), 'https://www.monsterinsights.com/plugin-feedback/' );
105
+ $feedback_url = monsterinsights_get_url( 'review-notice', 'feedback', $feedback_url );
106
+ // We have a candidate! Output a review message.
107
+ ?>
108
+ <div class="notice notice-info is-dismissible monsterinsights-review-notice">
109
+ <div class="monsterinsights-review-step monsterinsights-review-step-1">
110
+ <p><?php esc_html_e( 'Are you enjoying MonsterInsights?', 'google-analytics-for-wordpress' ); ?></p>
111
+ <p>
112
+ <a href="#" class="monsterinsights-review-switch-step" data-step="3"><?php esc_html_e( 'Yes', 'google-analytics-for-wordpress' ); ?></a><br />
113
+ <a href="#" class="monsterinsights-review-switch-step" data-step="2"><?php esc_html_e( 'Not Really', 'google-analytics-for-wordpress' ); ?></a>
114
+ </p>
115
+ </div>
116
+ <div class="monsterinsights-review-step monsterinsights-review-step-2" style="display: none">
117
+ <p><?php esc_html_e( 'We\'re sorry to hear you aren\'t enjoying MonsterInsights. We would love a chance to improve. Could you take a minute and let us know what we can do better?', 'google-analytics-for-wordpress' ); ?></p>
118
+ <p>
119
+ <a href="<?php echo esc_url( $feedback_url ); ?>" class="monsterinsights-dismiss-review-notice monsterinsights-review-out"><?php esc_html_e( 'Give Feedback', 'google-analytics-for-wordpress' ); ?></a><br>
120
+ <a href="#" class="monsterinsights-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'No thanks', 'google-analytics-for-wordpress' ); ?></a>
121
+ </p>
122
+ </div>
123
+ <div class="monsterinsights-review-step monsterinsights-review-step-3" style="display: none">
124
+ <p><?php esc_html_e( 'That’s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'google-analytics-for-wordpress' ); ?></p>
125
+ <p><strong><?php echo wp_kses( __( '~ Syed Balkhi<br>Co-Founder of MonsterInsights', 'google-analytics-for-wordpress' ), array( 'br' => array() ) ); ?></strong></p>
126
+ <p>
127
+ <a href="https://wordpress.org/support/plugin/google-analytics-for-wordpress/reviews/?filter=5#new-post" class="monsterinsights-dismiss-review-notice monsterinsights-review-out" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Ok, you deserve it', 'google-analytics-for-wordpress' ); ?></a><br>
128
+ <a href="#" class="monsterinsights-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Nope, maybe later', 'google-analytics-for-wordpress' ); ?></a><br>
129
+ <a href="#" class="monsterinsights-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'I already did', 'google-analytics-for-wordpress' ); ?></a>
130
+ </p>
131
+ </div>
132
+ </div>
133
+ <script type="text/javascript">
134
+ jQuery( document ).ready( function ( $ ) {
135
+ $( document ).on( 'click', '.monsterinsights-dismiss-review-notice, .monsterinsights-review-notice button', function ( event ) {
136
+ if ( ! $( this ).hasClass( 'monsterinsights-review-out' ) ) {
137
+ event.preventDefault();
138
+ }
139
+ $.post( ajaxurl, {
140
+ action: 'monsterinsights_review_dismiss'
141
+ } );
142
+ $( '.monsterinsights-review-notice' ).remove();
143
+ } );
144
+
145
+ $( document ).on( 'click', '.monsterinsights-review-switch-step', function ( e ) {
146
+ e.preventDefault();
147
+ var target = $( this ).attr( 'data-step' );
148
+ if ( target ) {
149
+ var notice = $( this ).closest( '.monsterinsights-review-notice' );
150
+ var review_step = notice.find( '.monsterinsights-review-step-' + target );
151
+ if ( review_step.length > 0 ) {
152
+ notice.find( '.monsterinsights-review-step:visible').fadeOut( function ( ) {
153
+ review_step.fadeIn();
154
+ });
155
+ }
156
+ }
157
+ })
158
+ } );
159
+ </script>
160
+ <?php
161
+ }
162
+ /**
163
+ * Dismiss the review admin notice
164
+ *
165
+ * @since 7.0.7
166
+ */
167
+ public function review_dismiss() {
168
+ $review = get_option( 'monsterinsights_review', array() );
169
+ $review['time'] = time();
170
+ $review['dismissed'] = true;
171
+ update_option( 'monsterinsights_review', $review );
172
+
173
+ if ( is_super_admin() && is_multisite() ) {
174
+ $site_list = get_sites();
175
+ foreach ( (array) $site_list as $site ) {
176
+ switch_to_blog( $site->blog_id );
177
+
178
+ update_option( 'monsterinsights_review', $review );
179
+
180
+ restore_current_blog();
181
+ }
182
+ }
183
+
184
+ die;
185
+ }
186
+ }
187
+
188
+ new MonsterInsights_Review();
includes/admin/routes.php CHANGED
@@ -1,657 +1,677 @@
1
- <?php
2
- /**
3
- * Routes for VUE are registered here.
4
- *
5
- * @package monsterinsights
6
- */
7
-
8
- /**
9
- * Class MonsterInsights_Rest_Routes
10
- */
11
- class MonsterInsights_Rest_Routes {
12
-
13
- /**
14
- * MonsterInsights_Rest_Routes constructor.
15
- */
16
- public function __construct() {
17
-
18
- add_action( 'wp_ajax_monsterinsights_vue_get_license', array( $this, 'get_license' ) );
19
- add_action( 'wp_ajax_monsterinsights_vue_get_profile', array( $this, 'get_profile' ) );
20
- add_action( 'wp_ajax_monsterinsights_vue_get_settings', array( $this, 'get_settings' ) );
21
- add_action( 'wp_ajax_monsterinsights_vue_update_settings', array( $this, 'update_settings' ) );
22
- add_action( 'wp_ajax_monsterinsights_vue_get_addons', array( $this, 'get_addons' ) );
23
- add_action( 'wp_ajax_monsterinsights_update_manual_ua', array( $this, 'update_manual_ua' ) );
24
- add_action( 'wp_ajax_monsterinsights_vue_get_report_data', array( $this, 'get_report_data' ) );
25
- add_action( 'wp_ajax_monsterinsights_vue_install_plugin', array( $this, 'install_plugin' ) );
26
-
27
- add_action( 'wp_ajax_monsterinsights_handle_settings_import', array( $this, 'handle_settings_import' ) );
28
-
29
- add_action( 'admin_notices', array( $this, 'hide_old_notices' ), 0 );
30
- }
31
-
32
- /**
33
- * Ajax handler for grabbing the license
34
- */
35
- public function get_license() {
36
-
37
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
38
-
39
- if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
40
- return;
41
- }
42
-
43
- $site_license = array(
44
- 'key' => MonsterInsights()->license->get_site_license_key(),
45
- 'type' => MonsterInsights()->license->get_site_license_type(),
46
- 'is_disabled' => MonsterInsights()->license->site_license_disabled(),
47
- 'is_expired' => MonsterInsights()->license->site_license_expired(),
48
- 'is_invalid' => MonsterInsights()->license->site_license_invalid(),
49
- );
50
- $network_license = array(
51
- 'key' => MonsterInsights()->license->get_network_license_key(),
52
- 'type' => MonsterInsights()->license->get_network_license_type(),
53
- 'is_disabled' => MonsterInsights()->license->network_license_disabled(),
54
- 'is_expired' => MonsterInsights()->license->network_license_expired(),
55
- 'is_invalid' => MonsterInsights()->license->network_license_disabled(),
56
- );
57
-
58
- wp_send_json( array(
59
- 'site' => $site_license,
60
- 'network' => $network_license,
61
- ) );
62
-
63
- }
64
-
65
- /**
66
- * Ajax handler for grabbing the license
67
- */
68
- public function get_profile() {
69
-
70
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
71
-
72
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
73
- return;
74
- }
75
-
76
- wp_send_json( array(
77
- 'ua' => MonsterInsights()->auth->get_ua(),
78
- 'viewname' => MonsterInsights()->auth->get_viewname(),
79
- 'manual_ua' => MonsterInsights()->auth->get_manual_ua(),
80
- 'network_ua' => MonsterInsights()->auth->get_network_ua(),
81
- 'network_viewname' => MonsterInsights()->auth->get_network_viewname(),
82
- 'network_manual_ua' => MonsterInsights()->auth->get_network_manual_ua(),
83
- ) );
84
-
85
- }
86
-
87
- /**
88
- * Ajax handler for grabbing the license
89
- */
90
- public function get_settings() {
91
-
92
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
93
-
94
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
95
- return;
96
- }
97
-
98
- $options = monsterinsights_get_options();
99
-
100
- // Array fields are needed even if empty.
101
- $array_fields = array( 'view_reports', 'save_settings', 'ignore_users' );
102
- foreach ( $array_fields as $array_field ) {
103
- if ( ! isset( $options[ $array_field ] ) ) {
104
- $options[ $array_field ] = array();
105
- }
106
- }
107
- if ( isset( $options['custom_code'] ) ) {
108
- $options['custom_code'] = stripslashes( $options['custom_code'] );
109
- }
110
-
111
- wp_send_json( $options );
112
-
113
- }
114
-
115
- /**
116
- * Ajax handler for grabbing the license
117
- */
118
- public function update_settings() {
119
-
120
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
121
-
122
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
123
- return;
124
- }
125
-
126
- if ( isset( $_POST['setting'] ) ) {
127
- $setting = sanitize_text_field( wp_unslash( $_POST['setting'] ) );
128
- if ( isset( $_POST['value'] ) ) {
129
- $value = $this->handle_sanitization( $setting, $_POST['value'] );
130
- monsterinsights_update_option( $setting, $value );
131
- } else {
132
- monsterinsights_update_option( $setting, false );
133
- }
134
- }
135
-
136
- wp_send_json_success();
137
-
138
- }
139
-
140
- /**
141
- * Sanitization specific to each field.
142
- *
143
- * @param string $field The key of the field to sanitize.
144
- * @param string $value The value of the field to sanitize.
145
- *
146
- * @return mixed The sanitized input.
147
- */
148
- private function handle_sanitization( $field, $value ) {
149
-
150
- $value = wp_unslash( $value );
151
-
152
- // Textarea fields.
153
- $textarea_fields = array(
154
- 'custom_code',
155
- );
156
-
157
- if ( in_array( $field, $textarea_fields, true ) ) {
158
- if ( function_exists( 'sanitize_textarea_field' ) ) {
159
- return sanitize_textarea_field( $value );
160
- } else {
161
- return wp_kses( $value, array() );
162
- }
163
- }
164
-
165
- $array_value = json_decode( $value, true );
166
- if ( is_array( $array_value ) ) {
167
- $value = $array_value;
168
- // Don't save empty values.
169
- foreach ( $value as $key => $item ) {
170
- if ( is_array( $item ) ) {
171
- $empty = true;
172
- foreach ( $item as $item_value ) {
173
- if ( ! empty( $item_value ) ) {
174
- $empty = false;
175
- }
176
- }
177
- if ( $empty ) {
178
- unset( $value[ $key ] );
179
- }
180
- }
181
- }
182
-
183
- // Reset array keys because JavaScript can't handle arrays with non-sequential keys.
184
- $value = array_values( $value );
185
-
186
- return $value;
187
- }
188
-
189
- return sanitize_text_field( $value );
190
-
191
- }
192
-
193
- /**
194
- * Return the state of the addons ( installed, activated )
195
- */
196
- public function get_addons() {
197
-
198
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
199
-
200
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
201
- return;
202
- }
203
-
204
- if ( isset( $_POST['network'] ) && intval( $_POST['network'] ) > 0 ) {
205
- define( 'WP_NETWORK_ADMIN', true );
206
- }
207
-
208
- $addons_data = monsterinsights_get_addons();
209
- $parsed_addons = array();
210
- $installed_plugins = get_plugins();
211
-
212
- if ( ! is_array( $addons_data ) ) {
213
- $addons_data = array();
214
- }
215
-
216
- foreach ( $addons_data as $addons_type => $addons ) {
217
- foreach ( $addons as $addon ) {
218
- $slug = 'monsterinsights-' . $addon->slug;
219
- if ( 'monsterinsights-ecommerce' === $slug ) {
220
- $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
221
- if ( empty( $addon->installed ) ) {
222
- $slug = 'ga-ecommerce';
223
- $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
224
- }
225
- } else {
226
- $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
227
- }
228
- $parsed_addons[ $addon->slug ] = $addon;
229
- }
230
- }
231
-
232
- // Include data about the plugins needed by some addons ( WooCommerce, EDD, Google AMP, CookieBot, etc ).
233
- // WooCommerce.
234
- $parsed_addons['woocommerce'] = array(
235
- 'active' => class_exists( 'WooCommerce' ),
236
- );
237
- // Edd.
238
- $parsed_addons['easy_digital_downloads'] = array(
239
- 'active' => class_exists( 'Easy_Digital_Downloads' ),
240
- );
241
- // MemberPress.
242
- $parsed_addons['memberpress'] = array(
243
- 'active' => defined( 'MEPR_VERSION' ) && version_compare( MEPR_VERSION, '1.3.43', '>' ),
244
- );
245
- // LifterLMS.
246
- $parsed_addons['lifterlms'] = array(
247
- 'active' => function_exists( 'LLMS' ) && version_compare( LLMS()->version, '3.32.0', '>=' ),
248
- );
249
- // Cookiebot.
250
- $parsed_addons['cookiebot'] = array(
251
- 'active' => function_exists( 'cookiebot_active' ) && cookiebot_active(),
252
- );
253
- // Cookie Notice.
254
- $parsed_addons['cookie_notice'] = array(
255
- 'active' => class_exists( 'Cookie_Notice' ),
256
- );
257
- // Fb Instant Articles.
258
- $parsed_addons['instant_articles'] = array(
259
- 'active' => defined( 'IA_PLUGIN_VERSION' ) && version_compare( IA_PLUGIN_VERSION, '3.3.4', '>' ),
260
- );
261
- // Google AMP.
262
- $parsed_addons['google_amp'] = array(
263
- 'active' => defined( 'AMP__FILE__' ),
264
- );
265
- // WPForms.
266
- $parsed_addons['wpforms'] = array(
267
- 'active' => function_exists( 'wpforms' ),
268
- 'icon' => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-wpforms.png',
269
- 'title' => 'WPForms',
270
- 'excerpt' => __( 'The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!', 'google-analytics-for-wordpress' ),
271
- 'installed' => array_key_exists( 'wpforms-lite/wpforms.php', $installed_plugins ),
272
- 'slug' => 'wpforms-lite',
273
- );
274
- // OptinMonster.
275
- $parsed_addons['optinmonster'] = array(
276
- 'active' => class_exists( 'OMAPI' ),
277
- 'icon' => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-om.png',
278
- 'title' => 'OptinMonster',
279
- 'excerpt' => __( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'google-analytics-for-wordpress' ),
280
- 'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
281
- 'basename' => 'optinmonster/optin-monster-wp-api.php',
282
- 'slug' => 'optinmonster',
283
- );
284
- // OptinMonster.
285
- $parsed_addons['wp-mail-smtp'] = array(
286
- 'active' => function_exists( 'wp_mail_smtp' ),
287
- 'icon' => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-smtp.png',
288
- 'title' => 'WP Mail SMTP',
289
- 'excerpt' => __( 'SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. SMTP helps increase email deliverability by using proper authentication', 'google-analytics-for-wordpress' ),
290
- 'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
291
- 'basename' => 'wp-mail-smtp/wp_mail_smtp.php',
292
- 'slug' => 'wp-mail-smtp',
293
- );
294
- // Gravity Forms.
295
- $parsed_addons['gravity_forms'] = array(
296
- 'active' => class_exists( 'GFCommon' ),
297
- );
298
- // Formidable Forms.
299
- $parsed_addons['formidable_forms'] = array(
300
- 'active' => class_exists( 'FrmHooksController' ),
301
- );
302
- // Manual UA Addon.
303
- if ( ! isset( $parsed_addons['manual_ua'] ) ) {
304
- $parsed_addons['manual_ua'] = array(
305
- 'active' => class_exists( 'MonsterInsights_Manual_UA' ),
306
- );
307
- }
308
-
309
- wp_send_json( $parsed_addons );
310
- }
311
-
312
- public function get_addon( $installed_plugins, $addons_type, $addon, $slug ) {
313
- $active = false;
314
- $installed = false;
315
- $plugin_basename = monsterinsights_get_plugin_basename_from_slug( $slug );
316
-
317
- if ( isset( $installed_plugins[ $plugin_basename ] ) ) {
318
- $installed = true;
319
- $ms_active = is_plugin_active_for_network( $plugin_basename );
320
- $ss_active = is_plugin_active( $plugin_basename );
321
-
322
- if ( is_multisite() && is_network_admin() ) {
323
- $active = is_plugin_active_for_network( $plugin_basename );
324
- } else {
325
- $active = is_plugin_active( $plugin_basename );
326
- }
327
- }
328
- if ( empty( $addon->url ) ) {
329
- $addon->url = '';
330
- }
331
-
332
- $addon->type = $addons_type;
333
- $addon->installed = $installed;
334
- $addon->active = $active;
335
- $addon->basename = $plugin_basename;
336
-
337
- return $addon;
338
- }
339
-
340
- /**
341
- * Use custom notices in the Vue app on the Settings screen.
342
- */
343
- public function hide_old_notices() {
344
-
345
- global $wp_version;
346
- if ( version_compare( $wp_version, '4.6', '<' ) ) {
347
- // remove_all_actions triggers an infinite loop on older versions.
348
- return;
349
- }
350
-
351
- $screen = get_current_screen();
352
- // Bail if we're not on a MonsterInsights screen.
353
- if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
354
- return;
355
- }
356
-
357
- // Hide admin notices on the settings screen.
358
- if ( monsterinsights_is_settings_page() ) {
359
- remove_all_actions( 'admin_notices' );
360
- }
361
-
362
- }
363
-
364
- /**
365
- * Update manual ua.
366
- */
367
- public function update_manual_ua() {
368
-
369
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
370
-
371
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
372
- return;
373
- }
374
-
375
- $manual_ua_code = isset( $_POST['manual_ua_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_ua_code'] ) ) : '';
376
- $manual_ua_code = monsterinsights_is_valid_ua( $manual_ua_code ); // Also sanitizes the string.
377
- $manual_ua_code_old = MonsterInsights()->auth->get_manual_ua();
378
- if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
379
- define( 'WP_NETWORK_ADMIN', true );
380
- }
381
-
382
- if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old === $manual_ua_code ) {
383
- // Same code we had before
384
- // Do nothing.
385
- wp_send_json_success();
386
- } else if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old !== $manual_ua_code ) {
387
- // Different UA code.
388
- if ( is_network_admin() ) {
389
- MonsterInsights()->auth->set_network_manual_ua( $manual_ua_code );
390
- } else {
391
- MonsterInsights()->auth->set_manual_ua( $manual_ua_code );
392
- }
393
- } else if ( $manual_ua_code && empty( $manual_ua_code_old ) ) {
394
- // Move to manual.
395
- if ( is_network_admin() ) {
396
- MonsterInsights()->auth->set_network_manual_ua( $manual_ua_code );
397
- } else {
398
- MonsterInsights()->auth->set_manual_ua( $manual_ua_code );
399
- }
400
- } else if ( empty( $manual_ua_code ) && $manual_ua_code_old ) {
401
- // Deleted manual.
402
- if ( is_network_admin() ) {
403
- MonsterInsights()->auth->delete_network_manual_ua();
404
- } else {
405
- MonsterInsights()->auth->delete_manual_ua();
406
- }
407
- } else if ( isset( $_POST['manual_ua_code'] ) && empty( $manual_ua_code ) ) {
408
- wp_send_json_error( array(
409
- 'error' => __( 'Invalid UA code', 'google-analytics-for-wordpress' ),
410
- ) );
411
- }
412
-
413
- wp_send_json_success();
414
- }
415
-
416
- /**
417
- *
418
- */
419
- public function handle_settings_import() {
420
-
421
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
422
-
423
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
424
- return;
425
- }
426
-
427
- if ( ! isset( $_FILES['import_file'] ) ) {
428
- return;
429
- }
430
-
431
- $extension = explode( '.', sanitize_text_field( wp_unslash( $_FILES['import_file']['name'] ) ) );
432
- $extension = end( $extension );
433
-
434
- if ( 'json' !== $extension ) {
435
- wp_send_json_error( array(
436
- 'message' => esc_html__( 'Please upload a valid .json file', 'google-analytics-for-wordpress' ),
437
- ) );
438
- }
439
-
440
- $import_file = sanitize_text_field( wp_unslash( $_FILES['import_file']['tmp_name'] ) );
441
-
442
- $file = file_get_contents( $import_file );
443
- if ( empty( $file ) ) {
444
- wp_send_json_error( array(
445
- 'message' => esc_html__( 'Please upload a file to import', 'google-analytics-for-wordpress' ),
446
- ) );
447
- }
448
-
449
- // Retrieve the settings from the file and convert the json object to an array.
450
- $new_settings = json_decode( wp_json_encode( json_decode( $file ) ), true );
451
- $settings = monsterinsights_get_options();
452
- $exclude = array(
453
- 'analytics_profile',
454
- 'analytics_profile_code',
455
- 'analytics_profile_name',
456
- 'oauth_version',
457
- 'cron_last_run',
458
- 'monsterinsights_oauth_status',
459
- );
460
-
461
- foreach ( $exclude as $e ) {
462
- if ( ! empty( $new_settings[ $e ] ) ) {
463
- unset( $new_settings[ $e ] );
464
- }
465
- }
466
-
467
- if ( ! is_super_admin() ) {
468
- if ( ! empty( $new_settings['custom_code'] ) ) {
469
- unset( $new_settings['custom_code'] );
470
- }
471
- }
472
-
473
- foreach ( $exclude as $e ) {
474
- if ( ! empty( $settings[ $e ] ) ) {
475
- $new_settings = $settings[ $e ];
476
- }
477
- }
478
-
479
- global $monsterinsights_settings;
480
- $monsterinsights_settings = $new_settings;
481
-
482
- update_option( monsterinsights_get_option_name(), $new_settings );
483
-
484
- wp_send_json_success( $new_settings );
485
-
486
- }
487
-
488
- /**
489
- * Generic Ajax handler for grabbing report data in JSON.
490
- */
491
- public function get_report_data() {
492
-
493
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
494
-
495
- if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
496
- wp_send_json_error( array( 'message' => __( "You don't have permission to view MonsterInsights reports.", 'google-analytics-for-wordpress' ) ) );
497
- }
498
-
499
- if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
500
- define( 'WP_NETWORK_ADMIN', true );
501
- }
502
- $settings_page = admin_url( 'admin.php?page=monsterinsights_settings' );
503
-
504
- // Only for Pro users, require a license key to be entered first so we can link to things.
505
- if ( monsterinsights_is_pro_version() ) {
506
- if ( ! MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->is_network_licensed() ) {
507
- wp_send_json_error( array(
508
- 'message' => __( "You can't view MonsterInsights reports because you are not licensed.", 'google-analytics-for-wordpress' ),
509
- 'footer' => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-for-wordpress' ) . '</a>',
510
- ) );
511
- } else if ( MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->site_license_has_error() ) {
512
- // Good to go: site licensed.
513
- } else if ( MonsterInsights()->license->is_network_licensed() && ! MonsterInsights()->license->network_license_has_error() ) {
514
- // Good to go: network licensed.
515
- } else {
516
- wp_send_json_error( array( 'message' => __( "You can't view MonsterInsights reports due to license key errors.", 'google-analytics-for-wordpress' ) ) );
517
- }
518
- }
519
-
520
- // We do not have a current auth.
521
- $site_auth = MonsterInsights()->auth->get_viewname();
522
- $ms_auth = is_multisite() && MonsterInsights()->auth->get_network_viewname();
523
- if ( ! $site_auth && ! $ms_auth ) {
524
- wp_send_json_error( array( 'message' => __( 'You must authenticate with MonsterInsights before you can view reports.', 'google-analytics-for-wordpress' ) ) );
525
- }
526
-
527
- $report_name = isset( $_POST['report'] ) ? sanitize_text_field( wp_unslash( $_POST['report'] ) ) : '';
528
-
529
- if ( empty( $report_name ) ) {
530
- wp_send_json_error( array( 'message' => __( 'Unknown report. Try refreshing and retrying. Contact support if this issue persists.', 'google-analytics-for-wordpress' ) ) );
531
- }
532
-
533
- $report = MonsterInsights()->reporting->get_report( $report_name );
534
-
535
- $isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
536
- $start = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : '';
537
- $end = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : '';
538
- $args = array(
539
- 'start' => $start,
540
- 'end' => $end,
541
- );
542
- if ( $isnetwork ) {
543
- $args['network'] = true;
544
- }
545
-
546
- if ( ! MonsterInsights()->license->license_can( $report->level ) ) {
547
- $data = array(
548
- 'success' => false,
549
- 'error' => 'license_level',
550
- );
551
- } else {
552
- $data = apply_filters( 'monsterinsights_vue_reports_data', $report->get_data( $args ), $report_name, $report );
553
- }
554
-
555
- if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
556
- wp_send_json_success( $data['data'] );
557
- } else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
558
- wp_send_json_error(
559
- array(
560
- 'message' => $data['error'],
561
- 'footer' => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
562
- )
563
- );
564
- }
565
-
566
- wp_send_json_error( array( 'message' => __( 'We encountered an error when fetching the report data.', 'google-analytics-for-wordpress' ) ) );
567
-
568
- }
569
-
570
- /**
571
- * Install plugins which are not addons.
572
- */
573
- public function install_plugin() {
574
- check_ajax_referer( 'mi-admin-nonce', 'nonce' );
575
-
576
- if ( ! current_user_can( 'install_plugins' ) ) {
577
- wp_send_json( array(
578
- 'message' => esc_html__( 'You are not allowed to install plugins', 'ga-premium' ),
579
- ) );
580
- }
581
-
582
- $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : false;
583
-
584
- if ( ! $slug ) {
585
- wp_send_json( array(
586
- 'message' => esc_html__( 'Missing plugin name.', 'ga-premium' ),
587
- ) );
588
- }
589
-
590
- include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
591
-
592
- $api = plugins_api( 'plugin_information', array(
593
- 'slug' => $slug,
594
- 'fields' => array(
595
- 'short_description' => false,
596
- 'sections' => false,
597
- 'requires' => false,
598
- 'rating' => false,
599
- 'ratings' => false,
600
- 'downloaded' => false,
601
- 'last_updated' => false,
602
- 'added' => false,
603
- 'tags' => false,
604
- 'compatibility' => false,
605
- 'homepage' => false,
606
- 'donate_link' => false,
607
- ),
608
- ) );
609
-
610
- if ( is_wp_error( $api ) ) {
611
- return $api->get_error_message();
612
- }
613
-
614
- $download_url = $api->download_link;
615
-
616
- $method = '';
617
- $url = add_query_arg(
618
- array(
619
- 'page' => 'monsterinsights-settings',
620
- ),
621
- admin_url( 'admin.php' )
622
- );
623
- $url = esc_url( $url );
624
-
625
- ob_start();
626
- if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
627
- $form = ob_get_clean();
628
-
629
- wp_send_json( array( 'form' => $form ) );
630
- }
631
-
632
- // If we are not authenticated, make it happen now.
633
- if ( ! WP_Filesystem( $creds ) ) {
634
- ob_start();
635
- request_filesystem_credentials( $url, $method, true, false, null );
636
- $form = ob_get_clean();
637
-
638
- wp_send_json( array( 'form' => $form ) );
639
-
640
- }
641
-
642
- // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
643
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
644
- $base = MonsterInsights();
645
- require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin.php';
646
-
647
- // Create the plugin upgrader with our custom skin.
648
- $installer = new Plugin_Upgrader( new MonsterInsights_Skin() );
649
- $installer->install( $download_url );
650
-
651
- // Flush the cache and return the newly installed plugin basename.
652
- wp_cache_flush();
653
- wp_send_json_success();
654
-
655
- wp_die();
656
- }
657
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Routes for VUE are registered here.
4
+ *
5
+ * @package monsterinsights
6
+ */
7
+
8
+ /**
9
+ * Class MonsterInsights_Rest_Routes
10
+ */
11
+ class MonsterInsights_Rest_Routes {
12
+
13
+ /**
14
+ * MonsterInsights_Rest_Routes constructor.
15
+ */
16
+ public function __construct() {
17
+
18
+ add_action( 'wp_ajax_monsterinsights_vue_get_license', array( $this, 'get_license' ) );
19
+ add_action( 'wp_ajax_monsterinsights_vue_get_profile', array( $this, 'get_profile' ) );
20
+ add_action( 'wp_ajax_monsterinsights_vue_get_settings', array( $this, 'get_settings' ) );
21
+ add_action( 'wp_ajax_monsterinsights_vue_update_settings', array( $this, 'update_settings' ) );
22
+ add_action( 'wp_ajax_monsterinsights_vue_get_addons', array( $this, 'get_addons' ) );
23
+ add_action( 'wp_ajax_monsterinsights_update_manual_ua', array( $this, 'update_manual_ua' ) );
24
+ add_action( 'wp_ajax_monsterinsights_vue_get_report_data', array( $this, 'get_report_data' ) );
25
+ add_action( 'wp_ajax_monsterinsights_vue_install_plugin', array( $this, 'install_plugin' ) );
26
+
27
+ add_action( 'wp_ajax_monsterinsights_handle_settings_import', array( $this, 'handle_settings_import' ) );
28
+
29
+ add_action( 'admin_notices', array( $this, 'hide_old_notices' ), 0 );
30
+
31
+ add_action( 'wp_ajax_monsterinsights_vue_dismiss_first_time_notice', array( $this, 'dismiss_first_time_notice' ) );
32
+ }
33
+
34
+ /**
35
+ * Ajax handler for grabbing the license
36
+ */
37
+ public function get_license() {
38
+
39
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
40
+
41
+ if ( ! current_user_can( 'monsterinsights_view_dashboard' ) || ! monsterinsights_is_pro_version() ) {
42
+ return;
43
+ }
44
+
45
+ $site_license = array(
46
+ 'key' => MonsterInsights()->license->get_site_license_key(),
47
+ 'type' => MonsterInsights()->license->get_site_license_type(),
48
+ 'is_disabled' => MonsterInsights()->license->site_license_disabled(),
49
+ 'is_expired' => MonsterInsights()->license->site_license_expired(),
50
+ 'is_invalid' => MonsterInsights()->license->site_license_invalid(),
51
+ );
52
+ $network_license = array(
53
+ 'key' => MonsterInsights()->license->get_network_license_key(),
54
+ 'type' => MonsterInsights()->license->get_network_license_type(),
55
+ 'is_disabled' => MonsterInsights()->license->network_license_disabled(),
56
+ 'is_expired' => MonsterInsights()->license->network_license_expired(),
57
+ 'is_invalid' => MonsterInsights()->license->network_license_disabled(),
58
+ );
59
+
60
+ wp_send_json( array(
61
+ 'site' => $site_license,
62
+ 'network' => $network_license,
63
+ ) );
64
+
65
+ }
66
+
67
+ /**
68
+ * Ajax handler for grabbing the current authenticated profile.
69
+ */
70
+ public function get_profile() {
71
+
72
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
73
+
74
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
75
+ return;
76
+ }
77
+
78
+ wp_send_json( array(
79
+ 'ua' => MonsterInsights()->auth->get_ua(),
80
+ 'viewname' => MonsterInsights()->auth->get_viewname(),
81
+ 'manual_ua' => MonsterInsights()->auth->get_manual_ua(),
82
+ 'network_ua' => MonsterInsights()->auth->get_network_ua(),
83
+ 'network_viewname' => MonsterInsights()->auth->get_network_viewname(),
84
+ 'network_manual_ua' => MonsterInsights()->auth->get_network_manual_ua(),
85
+ ) );
86
+
87
+ }
88
+
89
+ /**
90
+ * Ajax handler for grabbing the settings.
91
+ */
92
+ public function get_settings() {
93
+
94
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
95
+
96
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
97
+ return;
98
+ }
99
+
100
+ $options = monsterinsights_get_options();
101
+
102
+ // Array fields are needed even if empty.
103
+ $array_fields = array( 'view_reports', 'save_settings', 'ignore_users' );
104
+ foreach ( $array_fields as $array_field ) {
105
+ if ( ! isset( $options[ $array_field ] ) ) {
106
+ $options[ $array_field ] = array();
107
+ }
108
+ }
109
+ if ( isset( $options['custom_code'] ) ) {
110
+ $options['custom_code'] = stripslashes( $options['custom_code'] );
111
+ }
112
+
113
+ wp_send_json( $options );
114
+
115
+ }
116
+
117
+ /**
118
+ * Ajax handler for updating the settings.
119
+ */
120
+ public function update_settings() {
121
+
122
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
123
+
124
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
125
+ return;
126
+ }
127
+
128
+ if ( isset( $_POST['setting'] ) ) {
129
+ $setting = sanitize_text_field( wp_unslash( $_POST['setting'] ) );
130
+ if ( isset( $_POST['value'] ) ) {
131
+ $value = $this->handle_sanitization( $setting, $_POST['value'] );
132
+ monsterinsights_update_option( $setting, $value );
133
+ } else {
134
+ monsterinsights_update_option( $setting, false );
135
+ }
136
+ }
137
+
138
+ wp_send_json_success();
139
+
140
+ }
141
+
142
+ /**
143
+ * Sanitization specific to each field.
144
+ *
145
+ * @param string $field The key of the field to sanitize.
146
+ * @param string $value The value of the field to sanitize.
147
+ *
148
+ * @return mixed The sanitized input.
149
+ */
150
+ private function handle_sanitization( $field, $value ) {
151
+
152
+ $value = wp_unslash( $value );
153
+
154
+ // Textarea fields.
155
+ $textarea_fields = array(
156
+ 'custom_code',
157
+ );
158
+
159
+ if ( in_array( $field, $textarea_fields, true ) ) {
160
+ if ( function_exists( 'sanitize_textarea_field' ) ) {
161
+ return sanitize_textarea_field( $value );
162
+ } else {
163
+ return wp_kses( $value, array() );
164
+ }
165
+ }
166
+
167
+ $array_value = json_decode( $value, true );
168
+ if ( is_array( $array_value ) ) {
169
+ $value = $array_value;
170
+ // Don't save empty values.
171
+ foreach ( $value as $key => $item ) {
172
+ if ( is_array( $item ) ) {
173
+ $empty = true;
174
+ foreach ( $item as $item_value ) {
175
+ if ( ! empty( $item_value ) ) {
176
+ $empty = false;
177
+ }
178
+ }
179
+ if ( $empty ) {
180
+ unset( $value[ $key ] );
181
+ }
182
+ }
183
+ }
184
+
185
+ // Reset array keys because JavaScript can't handle arrays with non-sequential keys.
186
+ $value = array_values( $value );
187
+
188
+ return $value;
189
+ }
190
+
191
+ return sanitize_text_field( $value );
192
+
193
+ }
194
+
195
+ /**
196
+ * Return the state of the addons ( installed, activated )
197
+ */
198
+ public function get_addons() {
199
+
200
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
201
+
202
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
203
+ return;
204
+ }
205
+
206
+ if ( isset( $_POST['network'] ) && intval( $_POST['network'] ) > 0 ) {
207
+ define( 'WP_NETWORK_ADMIN', true );
208
+ }
209
+
210
+ $addons_data = monsterinsights_get_addons();
211
+ $parsed_addons = array();
212
+ $installed_plugins = get_plugins();
213
+
214
+ if ( ! is_array( $addons_data ) ) {
215
+ $addons_data = array();
216
+ }
217
+
218
+ foreach ( $addons_data as $addons_type => $addons ) {
219
+ foreach ( $addons as $addon ) {
220
+ $slug = 'monsterinsights-' . $addon->slug;
221
+ if ( 'monsterinsights-ecommerce' === $slug ) {
222
+ $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
223
+ if ( empty( $addon->installed ) ) {
224
+ $slug = 'ga-ecommerce';
225
+ $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
226
+ }
227
+ } else {
228
+ $addon = $this->get_addon( $installed_plugins, $addons_type, $addon, $slug );
229
+ }
230
+ $parsed_addons[ $addon->slug ] = $addon;
231
+ }
232
+ }
233
+
234
+ // Include data about the plugins needed by some addons ( WooCommerce, EDD, Google AMP, CookieBot, etc ).
235
+ // WooCommerce.
236
+ $parsed_addons['woocommerce'] = array(
237
+ 'active' => class_exists( 'WooCommerce' ),
238
+ );
239
+ // Edd.
240
+ $parsed_addons['easy_digital_downloads'] = array(
241
+ 'active' => class_exists( 'Easy_Digital_Downloads' ),
242
+ );
243
+ // MemberPress.
244
+ $parsed_addons['memberpress'] = array(
245
+ 'active' => defined( 'MEPR_VERSION' ) && version_compare( MEPR_VERSION, '1.3.43', '>' ),
246
+ );
247
+ // LifterLMS.
248
+ $parsed_addons['lifterlms'] = array(
249
+ 'active' => function_exists( 'LLMS' ) && version_compare( LLMS()->version, '3.32.0', '>=' ),
250
+ );
251
+ // Cookiebot.
252
+ $parsed_addons['cookiebot'] = array(
253
+ 'active' => function_exists( 'cookiebot_active' ) && cookiebot_active(),
254
+ );
255
+ // Cookie Notice.
256
+ $parsed_addons['cookie_notice'] = array(
257
+ 'active' => class_exists( 'Cookie_Notice' ),
258
+ );
259
+ // Fb Instant Articles.
260
+ $parsed_addons['instant_articles'] = array(
261
+ 'active' => defined( 'IA_PLUGIN_VERSION' ) && version_compare( IA_PLUGIN_VERSION, '3.3.4', '>' ),
262
+ );
263
+ // Google AMP.
264
+ $parsed_addons['google_amp'] = array(
265
+ 'active' => defined( 'AMP__FILE__' ),
266
+ );
267
+ // WPForms.
268
+ $parsed_addons['wpforms'] = array(
269
+ 'active' => function_exists( 'wpforms' ),
270
+ 'icon' => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-wpforms.png',
271
+ 'title' => 'WPForms',
272
+ 'excerpt' => __( 'The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!', 'google-analytics-for-wordpress' ),
273
+ 'installed' => array_key_exists( 'wpforms-lite/wpforms.php', $installed_plugins ),
274
+ 'slug' => 'wpforms-lite',
275
+ );
276
+ // OptinMonster.
277
+ $parsed_addons['optinmonster'] = array(
278
+ 'active' => class_exists( 'OMAPI' ),
279
+ 'icon' => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-om.png',
280
+ 'title' => 'OptinMonster',
281
+ 'excerpt' => __( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'google-analytics-for-wordpress' ),
282
+ 'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
283
+ 'basename' => 'optinmonster/optin-monster-wp-api.php',
284
+ 'slug' => 'optinmonster',
285
+ );
286
+ // OptinMonster.
287
+ $parsed_addons['wp-mail-smtp'] = array(
288
+ 'active' => function_exists( 'wp_mail_smtp' ),
289
+ 'icon' => plugin_dir_url( MONSTERINSIGHTS_PLUGIN_FILE ) . 'assets/images/plugin-smtp.png',
290
+ 'title' => 'WP Mail SMTP',
291
+ 'excerpt' => __( 'SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. SMTP helps increase email deliverability by using proper authentication', 'google-analytics-for-wordpress' ),
292
+ 'installed' => array_key_exists( 'optinmonster/optin-monster-wp-api.php', $installed_plugins ),
293
+ 'basename' => 'wp-mail-smtp/wp_mail_smtp.php',
294
+ 'slug' => 'wp-mail-smtp',
295
+ );
296
+ // Gravity Forms.
297
+ $parsed_addons['gravity_forms'] = array(
298
+ 'active' => class_exists( 'GFCommon' ),
299
+ );
300
+ // Formidable Forms.
301
+ $parsed_addons['formidable_forms'] = array(
302
+ 'active' => class_exists( 'FrmHooksController' ),
303
+ );
304
+ // Manual UA Addon.
305
+ if ( ! isset( $parsed_addons['manual_ua'] ) ) {
306
+ $parsed_addons['manual_ua'] = array(
307
+ 'active' => class_exists( 'MonsterInsights_Manual_UA' ),
308
+ );
309
+ }
310
+
311
+ wp_send_json( $parsed_addons );
312
+ }
313
+
314
+ public function get_addon( $installed_plugins, $addons_type, $addon, $slug ) {
315
+ $active = false;
316
+ $installed = false;
317
+ $plugin_basename = monsterinsights_get_plugin_basename_from_slug( $slug );
318
+
319
+ if ( isset( $installed_plugins[ $plugin_basename ] ) ) {
320
+ $installed = true;
321
+
322
+ if ( is_multisite() && is_network_admin() ) {
323
+ $active = is_plugin_active_for_network( $plugin_basename );
324
+ } else {
325
+ $active = is_plugin_active( $plugin_basename );
326
+ }
327
+ }
328
+ if ( empty( $addon->url ) ) {
329
+ $addon->url = '';
330
+ }
331
+
332
+ $addon->type = $addons_type;
333
+ $addon->installed = $installed;
334
+ $addon->active = $active;
335
+ $addon->basename = $plugin_basename;
336
+
337
+ return $addon;
338
+ }
339
+
340
+ /**
341
+ * Use custom notices in the Vue app on the Settings screen.
342
+ */
343
+ public function hide_old_notices() {
344
+
345
+ global $wp_version;
346
+ if ( version_compare( $wp_version, '4.6', '<' ) ) {
347
+ // remove_all_actions triggers an infinite loop on older versions.
348
+ return;
349
+ }
350
+
351
+ $screen = get_current_screen();
352
+ // Bail if we're not on a MonsterInsights screen.
353
+ if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
354
+ return;
355
+ }
356
+
357
+ // Hide admin notices on the settings screen.
358
+ if ( monsterinsights_is_settings_page() ) {
359
+ remove_all_actions( 'admin_notices' );
360
+ }
361
+
362
+ }
363
+
364
+ /**
365
+ * Update manual ua.
366
+ */
367
+ public function update_manual_ua() {
368
+
369
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
370
+
371
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
372
+ return;
373
+ }
374
+
375
+ $manual_ua_code = isset( $_POST['manual_ua_code'] ) ? sanitize_text_field( wp_unslash( $_POST['manual_ua_code'] ) ) : '';
376
+ $manual_ua_code = monsterinsights_is_valid_ua( $manual_ua_code ); // Also sanitizes the string.
377
+ $manual_ua_code_old = MonsterInsights()->auth->get_manual_ua();
378
+ if ( ! empty( $_REQUEST['isnetwork'] ) && sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) ) {
379
+ define( 'WP_NETWORK_ADMIN', true );
380
+ }
381
+
382
+ if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old === $manual_ua_code ) {
383
+ // Same code we had before
384
+ // Do nothing.
385
+ wp_send_json_success();
386
+ } else if ( $manual_ua_code && $manual_ua_code_old && $manual_ua_code_old !== $manual_ua_code ) {
387
+ // Different UA code.
388
+ if ( is_network_admin() ) {
389
+ MonsterInsights()->auth->set_network_manual_ua( $manual_ua_code );
390
+ } else {
391
+ MonsterInsights()->auth->set_manual_ua( $manual_ua_code );
392
+ }
393
+ } else if ( $manual_ua_code && empty( $manual_ua_code_old ) ) {
394
+ // Move to manual.
395
+ if ( is_network_admin() ) {
396
+ MonsterInsights()->auth->set_network_manual_ua( $manual_ua_code );
397
+ } else {
398
+ MonsterInsights()->auth->set_manual_ua( $manual_ua_code );
399
+ }
400
+ } else if ( empty( $manual_ua_code ) && $manual_ua_code_old ) {
401
+ // Deleted manual.
402
+ if ( is_network_admin() ) {
403
+ MonsterInsights()->auth->delete_network_manual_ua();
404
+ } else {
405
+ MonsterInsights()->auth->delete_manual_ua();
406
+ }
407
+ } else if ( isset( $_POST['manual_ua_code'] ) && empty( $manual_ua_code ) ) {
408
+ wp_send_json_error( array(
409
+ 'error' => __( 'Invalid UA code', 'google-analytics-for-wordpress' ),
410
+ ) );
411
+ }
412
+
413
+ wp_send_json_success();
414
+ }
415
+
416
+ /**
417
+ *
418
+ */
419
+ public function handle_settings_import() {
420
+
421
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
422
+
423
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
424
+ return;
425
+ }
426
+
427
+ if ( ! isset( $_FILES['import_file'] ) ) {
428
+ return;
429
+ }
430
+
431
+ $extension = explode( '.', sanitize_text_field( wp_unslash( $_FILES['import_file']['name'] ) ) );
432
+ $extension = end( $extension );
433
+
434
+ if ( 'json' !== $extension ) {
435
+ wp_send_json_error( array(
436
+ 'message' => esc_html__( 'Please upload a valid .json file', 'google-analytics-for-wordpress' ),
437
+ ) );
438
+ }
439
+
440
+ $import_file = sanitize_text_field( wp_unslash( $_FILES['import_file']['tmp_name'] ) );
441
+
442
+ $file = file_get_contents( $import_file );
443
+ if ( empty( $file ) ) {
444
+ wp_send_json_error( array(
445
+ 'message' => esc_html__( 'Please upload a file to import', 'google-analytics-for-wordpress' ),
446
+ ) );
447
+ }
448
+
449
+ // Retrieve the settings from the file and convert the json object to an array.
450
+ $new_settings = json_decode( wp_json_encode( json_decode( $file ) ), true );
451
+ $settings = monsterinsights_get_options();
452
+ $exclude = array(
453
+ 'analytics_profile',
454
+ 'analytics_profile_code',
455
+ 'analytics_profile_name',
456
+ 'oauth_version',
457
+ 'cron_last_run',
458
+ 'monsterinsights_oauth_status',
459
+ );
460
+
461
+ foreach ( $exclude as $e ) {
462
+ if ( ! empty( $new_settings[ $e ] ) ) {
463
+ unset( $new_settings[ $e ] );
464
+ }
465
+ }
466
+
467
+ if ( ! is_super_admin() ) {
468
+ if ( ! empty( $new_settings['custom_code'] ) ) {
469
+ unset( $new_settings['custom_code'] );
470
+ }
471
+ }
472
+
473
+ foreach ( $exclude as $e ) {
474
+ if ( ! empty( $settings[ $e ] ) ) {
475
+ $new_settings = $settings[ $e ];
476
+ }
477
+ }
478
+
479
+ global $monsterinsights_settings;
480
+ $monsterinsights_settings = $new_settings;
481
+
482
+ update_option( monsterinsights_get_option_name(), $new_settings );
483
+
484
+ wp_send_json_success( $new_settings );
485
+
486
+ }
487
+
488
+ /**
489
+ * Generic Ajax handler for grabbing report data in JSON.
490
+ */
491
+ public function get_report_data() {
492
+
493
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
494
+
495
+ if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) {
496
+ wp_send_json_error( array( 'message' => __( "You don't have permission to view MonsterInsights reports.", 'google-analytics-for-wordpress' ) ) );
497
+ }
498
+
499
+ if ( ! empty( $_REQUEST['isnetwork'] ) && $_REQUEST['isnetwork'] ) {
500
+ define( 'WP_NETWORK_ADMIN', true );
501
+ }
502
+ $settings_page = admin_url( 'admin.php?page=monsterinsights_settings' );
503
+
504
+ // Only for Pro users, require a license key to be entered first so we can link to things.
505
+ if ( monsterinsights_is_pro_version() ) {
506
+ if ( ! MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->is_network_licensed() ) {
507
+ wp_send_json_error( array(
508
+ 'message' => __( "You can't view MonsterInsights reports because you are not licensed.", 'google-analytics-for-wordpress' ),
509
+ 'footer' => '<a href="' . $settings_page . '">' . __( 'Add your license', 'google-analytics-for-wordpress' ) . '</a>',
510
+ ) );
511
+ } else if ( MonsterInsights()->license->is_site_licensed() && ! MonsterInsights()->license->site_license_has_error() ) {
512
+ // Good to go: site licensed.
513
+ } else if ( MonsterInsights()->license->is_network_licensed() && ! MonsterInsights()->license->network_license_has_error() ) {
514
+ // Good to go: network licensed.
515
+ } else {
516
+ wp_send_json_error( array( 'message' => __( "You can't view MonsterInsights reports due to license key errors.", 'google-analytics-for-wordpress' ) ) );
517
+ }
518
+ }
519
+
520
+ // We do not have a current auth.
521
+ $site_auth = MonsterInsights()->auth->get_viewname();
522
+ $ms_auth = is_multisite() && MonsterInsights()->auth->get_network_viewname();
523
+ if ( ! $site_auth && ! $ms_auth ) {
524
+ wp_send_json_error( array( 'message' => __( 'You must authenticate with MonsterInsights before you can view reports.', 'google-analytics-for-wordpress' ) ) );
525
+ }
526
+
527
+ $report_name = isset( $_POST['report'] ) ? sanitize_text_field( wp_unslash( $_POST['report'] ) ) : '';
528
+
529
+ if ( empty( $report_name ) ) {
530
+ wp_send_json_error( array( 'message' => __( 'Unknown report. Try refreshing and retrying. Contact support if this issue persists.', 'google-analytics-for-wordpress' ) ) );
531
+ }
532
+
533
+ $report = MonsterInsights()->reporting->get_report( $report_name );
534
+
535
+ $isnetwork = ! empty( $_REQUEST['isnetwork'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['isnetwork'] ) ) : '';
536
+ $start = ! empty( $_POST['start'] ) ? sanitize_text_field( wp_unslash( $_POST['start'] ) ) : '';
537
+ $end = ! empty( $_POST['end'] ) ? sanitize_text_field( wp_unslash( $_POST['end'] ) ) : '';
538
+ $args = array(
539
+ 'start' => $start,
540
+ 'end' => $end,
541
+ );
542
+ if ( $isnetwork ) {
543
+ $args['network'] = true;
544
+ }
545
+
546
+ if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $report->level ) ) {
547
+ $data = array(
548
+ 'success' => false,
549
+ 'error' => 'license_level',
550
+ );
551
+ } else {
552
+ $data = apply_filters( 'monsterinsights_vue_reports_data', $report->get_data( $args ), $report_name, $report );
553
+ }
554
+
555
+ if ( ! empty( $data['success'] ) && ! empty( $data['data'] ) ) {
556
+ wp_send_json_success( $data['data'] );
557
+ } else if ( isset( $data['success'] ) && false === $data['success'] && ! empty( $data['error'] ) ) {
558
+ // Use a custom handler for invalid_grant errors.
559
+ if ( strpos( $data['error'], 'invalid_grant' ) > 0 ) {
560
+ wp_send_json_error(
561
+ array(
562
+ 'message' => 'invalid_grant',
563
+ 'footer' => '',
564
+ )
565
+ );
566
+ }
567
+
568
+ wp_send_json_error(
569
+ array(
570
+ 'message' => $data['error'],
571
+ 'footer' => isset( $data['data']['footer'] ) ? $data['data']['footer'] : '',
572
+ )
573
+ );
574
+ }
575
+
576
+ wp_send_json_error( array( 'message' => __( 'We encountered an error when fetching the report data.', 'google-analytics-for-wordpress' ) ) );
577
+
578
+ }
579
+
580
+ /**
581
+ * Install plugins which are not addons.
582
+ */
583
+ public function install_plugin() {
584
+ check_ajax_referer( 'mi-admin-nonce', 'nonce' );
585
+
586
+ if ( ! current_user_can( 'install_plugins' ) ) {
587
+ wp_send_json( array(
588
+ 'message' => esc_html__( 'You are not allowed to install plugins', 'ga-premium' ),
589
+ ) );
590
+ }
591
+
592
+ $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : false;
593
+
594
+ if ( ! $slug ) {
595
+ wp_send_json( array(
596
+ 'message' => esc_html__( 'Missing plugin name.', 'ga-premium' ),
597
+ ) );
598
+ }
599
+
600
+ include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
601
+
602
+ $api = plugins_api( 'plugin_information', array(
603
+ 'slug' => $slug,
604
+ 'fields' => array(
605
+ 'short_description' => false,
606
+ 'sections' => false,
607
+ 'requires' => false,
608
+ 'rating' => false,
609
+ 'ratings' => false,
610
+ 'downloaded' => false,
611
+ 'last_updated' => false,
612
+ 'added' => false,
613
+ 'tags' => false,
614
+ 'compatibility' => false,
615
+ 'homepage' => false,
616
+ 'donate_link' => false,
617
+ ),
618
+ ) );
619
+
620
+ if ( is_wp_error( $api ) ) {
621
+ return $api->get_error_message();
622
+ }
623
+
624
+ $download_url = $api->download_link;
625
+
626
+ $method = '';
627
+ $url = add_query_arg(
628
+ array(
629
+ 'page' => 'monsterinsights-settings',
630
+ ),
631
+ admin_url( 'admin.php' )
632
+ );
633
+ $url = esc_url( $url );
634
+
635
+ ob_start();
636
+ if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
637
+ $form = ob_get_clean();
638
+
639
+ wp_send_json( array( 'form' => $form ) );
640
+ }
641
+
642
+ // If we are not authenticated, make it happen now.
643
+ if ( ! WP_Filesystem( $creds ) ) {
644
+ ob_start();
645
+ request_filesystem_credentials( $url, $method, true, false, null );
646
+ $form = ob_get_clean();
647
+
648
+ wp_send_json( array( 'form' => $form ) );
649
+
650
+ }
651
+
652
+ // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
653
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
654
+ $base = MonsterInsights();
655
+ require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin.php';
656
+
657
+ // Create the plugin upgrader with our custom skin.
658
+ $installer = new Plugin_Upgrader( new MonsterInsights_Skin() );
659
+ $installer->install( $download_url );
660
+
661
+ // Flush the cache and return the newly installed plugin basename.
662
+ wp_cache_flush();
663
+ wp_send_json_success();
664
+
665
+ wp_die();
666
+ }
667
+
668
+ /**
669
+ * Store that the first run notice has been dismissed so it doesn't show up again.
670
+ */
671
+ public function dismiss_first_time_notice() {
672
+
673
+ monsterinsights_update_option( 'monsterinsights_first_run_notice', true );
674
+
675
+ wp_send_json_success();
676
+ }
677
+ }
includes/admin/tracking.php CHANGED
@@ -1,247 +1,247 @@
1
- <?php
2
- /**
3
- * Tracking functions for reporting plugin usage to the MonsterInsights site for users that have opted in
4
- *
5
- * @package MonsterInsights
6
- * @subpackage Admin
7
- * @copyright Copyright (c) 2018, Chris Christoff
8
- * @since 7.0.0
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
- /**
17
- * Usage tracking
18
- *
19
- * @access public
20
- * @since 7.0.0
21
- * @return void
22
- */
23
- class MonsterInsights_Tracking {
24
-
25
- public function __construct() {
26
- add_action( 'init', array( $this, 'schedule_send' ) );
27
- add_action( 'monsterinsights_settings_save_general_end', array( $this, 'check_for_settings_optin' ) );
28
- add_action( 'admin_head', array( $this, 'check_for_optin' ) );
29
- add_action( 'admin_head', array( $this, 'check_for_optout' ) );
30
- add_filter( 'cron_schedules', array( $this, 'add_schedules' ) );
31
- add_action( 'monsterinsights_usage_tracking_cron', array( $this, 'send_checkin' ) );
32
- }
33
-
34
- private function get_data() {
35
- $data = array();
36
-
37
- // Retrieve current theme info
38
- $theme_data = wp_get_theme();
39
- $tracking_mode = monsterinsights_get_option( 'tracking_mode', 'analytics' );
40
- $events_mode = monsterinsights_get_option( 'events_mode', 'none' );
41
- $update_mode = monsterinsights_get_option( 'automatic_updates', false );
42
-
43
- if ( $tracking_mode === false ) {
44
- $tracking_mode = 'analytics';
45
- }
46
- if ( $events_mode === false ) {
47
- $events_mode = 'none';
48
- }
49
-
50
- if ( $update_mode === false ) {
51
- $update_mode = 'none';
52
- }
53
-
54
- $count_b = 1;
55
- if ( is_multisite() ) {
56
- if ( function_exists( 'get_blog_count' ) ) {
57
- $count_b = get_blog_count();
58
- } else {
59
- $count_b = 'Not Set';
60
- }
61
- }
62
-
63
- $usesauth = 'No';
64
- $local = MonsterInsights()->auth->is_authed();
65
- $network = MonsterInsights()->auth->is_network_authed();
66
-
67
- if ( $local && $network ) {
68
- $usesauth = 'Both';
69
- } else if ( $local ) {
70
- $usesauth = 'Local';
71
- } else if ( $network ) {
72
- $usesauth = 'Network';
73
- }
74
-
75
- $data['php_version'] = phpversion();
76
- $data['mi_version'] = MONSTERINSIGHTS_VERSION;
77
- $data['wp_version'] = get_bloginfo( 'version' );
78
- $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
79
- $data['over_time'] = get_option( 'monsterinsights_over_time', array() );
80
- $data['multisite'] = is_multisite();
81
- $data['url'] = home_url();
82
- $data['themename'] = $theme_data->Name;
83
- $data['themeversion'] = $theme_data->Version;
84
- $data['email'] = get_bloginfo( 'admin_email' );
85
- $data['key'] = monsterinsights_get_license_key();
86
- $data['sas'] = monsterinsights_get_shareasale_id();
87
- $data['settings'] = monsterinsights_get_options();
88
- $data['tracking_mode'] = $tracking_mode;
89
- $data['events_mode'] = $events_mode;
90
- $data['autoupdate'] = $update_mode;
91
- $data['pro'] = (int) monsterinsights_is_pro_version();
92
- $data['sites'] = $count_b;
93
- $data['usagetracking'] = get_option( 'monsterinsights_usage_tracking_config', false );
94
- $data['usercount'] = function_exists( 'get_user_count' ) ? get_user_count() : 'Not Set';
95
- $data['usesauth'] = $usesauth;
96
- $data['timezoneoffset']= date('P');
97
- $data['installed_lite']= get_option( 'monsterinsights_installed_lite', array() );
98
- $data['installed_pro'] = get_option( 'monsterinsights_installed_pro', array() );
99
-
100
-
101
-
102
- // Retrieve current plugin information
103
- if( ! function_exists( 'get_plugins' ) ) {
104
- include ABSPATH . '/wp-admin/includes/plugin.php';
105
- }
106
-
107
- $plugins = array_keys( get_plugins() );
108
- $active_plugins = get_option( 'active_plugins', array() );
109
-
110
- foreach ( $plugins as $key => $plugin ) {
111
- if ( in_array( $plugin, $active_plugins ) ) {
112
- // Remove active plugins from list so we can show active and inactive separately
113
- unset( $plugins[ $key ] );
114
- }
115
- }
116
-
117
- $data['active_plugins'] = $active_plugins;
118
- $data['inactive_plugins'] = $plugins;
119
- $data['locale'] = get_locale();
120
-
121
- return $data;
122
- }
123
-
124
- public function send_checkin( $override = false, $ignore_last_checkin = false ) {
125
-
126
- $home_url = trailingslashit( home_url() );
127
- if ( strpos( $home_url, 'monsterinsights.com' ) !== false ) {
128
- return false;
129
- }
130
-
131
- if( ! $this->tracking_allowed() && ! $override ) {
132
- return false;
133
- }
134
-
135
- // Send a maximum of once per week
136
- $last_send = get_option( 'monsterinsights_usage_tracking_last_checkin' );
137
- if ( is_numeric( $last_send ) && $last_send > strtotime( '-1 week' ) && ! $ignore_last_checkin ) {
138
- return false;
139
- }
140
-
141
- $request = wp_remote_post( 'https://miusage.com/v1/checkin/', array(
142
- 'method' => 'POST',
143
- 'timeout' => 5,
144
- 'redirection' => 5,
145
- 'httpversion' => '1.1',
146
- 'blocking' => false,
147
- 'body' => $this->get_data(),
148
- 'user-agent' => 'MI/' . MONSTERINSIGHTS_VERSION . '; ' . get_bloginfo( 'url' )
149
- ) );
150
-
151
- // If we have completed successfully, recheck in 1 week
152
- update_option( 'monsterinsights_usage_tracking_last_checkin', time() );
153
- return true;
154
- }
155
-
156
- private function tracking_allowed() {
157
- return (bool) monsterinsights_get_option( 'anonymous_data', false ) || monsterinsights_is_pro_version();
158
- }
159
-
160
- public function schedule_send() {
161
- if ( ! wp_next_scheduled( 'monsterinsights_usage_tracking_cron' ) ) {
162
- $tracking = array();
163
- $tracking['day'] = rand( 0, 6 );
164
- $tracking['hour'] = rand( 0, 23 );
165
- $tracking['minute'] = rand( 0, 59 );
166
- $tracking['second'] = rand( 0, 59 );
167
- $tracking['offset'] = ( $tracking['day'] * DAY_IN_SECONDS ) +
168
- ( $tracking['hour'] * HOUR_IN_SECONDS ) +
169
- ( $tracking['minute'] * MINUTE_IN_SECONDS ) +
170
- $tracking['second'];
171
- $tracking['initsend'] = strtotime("next sunday") + $tracking['offset'];
172
-
173
- wp_schedule_event( $tracking['initsend'], 'weekly', 'monsterinsights_usage_tracking_cron' );
174
- update_option( 'monsterinsights_usage_tracking_config', $tracking );
175
- }
176
- }
177
-
178
- public function check_for_settings_optin() {
179
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
180
- return;
181
- }
182
-
183
- if ( monsterinsights_is_pro_version() ) {
184
- return;
185
- }
186
-
187
- // Send an intial check in on settings save
188
- $anonymous_data = isset( $_POST['anonymous_data'] ) ? 1 : 0;
189
- if ( $anonymous_data ) {
190
- $this->send_checkin( true, true );
191
- }
192
-
193
- }
194
-
195
- public function check_for_optin() {
196
- if ( ! ( ! empty( $_REQUEST['mi_action'] ) && 'opt_into_tracking' === $_REQUEST['mi_action'] ) ) {
197
- return;
198
- }
199
-
200
- if ( monsterinsights_get_option( 'anonymous_data', false ) ) {
201
- return;
202
- }
203
-
204
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
205
- return;
206
- }
207
-
208
- if ( monsterinsights_is_pro_version() ) {
209
- return;
210
- }
211
-
212
- monsterinsights_update_option( 'anonymous_data', 1 );
213
- $this->send_checkin( true, true );
214
- update_option( 'monsterinsights_tracking_notice', 1 );
215
- }
216
-
217
- public function check_for_optout() {
218
- if ( ! ( ! empty( $_REQUEST['mi_action'] ) && 'opt_out_of_tracking' === $_REQUEST['mi_action'] ) ) {
219
- return;
220
- }
221
-
222
- if ( monsterinsights_get_option( 'anonymous_data', false ) ) {
223
- return;
224
- }
225
-
226
- if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
227
- return;
228
- }
229
-
230
- if ( monsterinsights_is_pro_version() ) {
231
- return;
232
- }
233
-
234
- monsterinsights_update_option( 'anonymous_data', 0 );
235
- update_option( 'monsterinsights_tracking_notice', 1 );
236
- }
237
-
238
- public function add_schedules( $schedules = array() ) {
239
- // Adds once weekly to the existing schedules.
240
- $schedules['weekly'] = array(
241
- 'interval' => 604800,
242
- 'display' => __( 'Once Weekly', 'google-analytics-for-wordpress' )
243
- );
244
- return $schedules;
245
- }
246
- }
247
  new MonsterInsights_Tracking();
1
+ <?php
2
+ /**
3
+ * Tracking functions for reporting plugin usage to the MonsterInsights site for users that have opted in
4
+ *
5
+ * @package MonsterInsights
6
+ * @subpackage Admin
7
+ * @copyright Copyright (c) 2018, Chris Christoff
8
+ * @since 7.0.0
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ /**
17
+ * Usage tracking
18
+ *
19
+ * @access public
20
+ * @since 7.0.0
21
+ * @return void
22
+ */
23
+ class MonsterInsights_Tracking {
24
+
25
+ public function __construct() {
26
+ add_action( 'init', array( $this, 'schedule_send' ) );
27
+ add_action( 'monsterinsights_settings_save_general_end', array( $this, 'check_for_settings_optin' ) );
28
+ add_action( 'admin_head', array( $this, 'check_for_optin' ) );
29
+ add_action( 'admin_head', array( $this, 'check_for_optout' ) );
30
+ add_filter( 'cron_schedules', array( $this, 'add_schedules' ) );
31
+ add_action( 'monsterinsights_usage_tracking_cron', array( $this, 'send_checkin' ) );
32
+ }
33
+
34
+ private function get_data() {
35
+ $data = array();
36
+
37
+ // Retrieve current theme info
38
+ $theme_data = wp_get_theme();
39
+ $tracking_mode = monsterinsights_get_option( 'tracking_mode', 'analytics' );
40
+ $events_mode = monsterinsights_get_option( 'events_mode', 'none' );
41
+ $update_mode = monsterinsights_get_option( 'automatic_updates', false );
42
+
43
+ if ( $tracking_mode === false ) {
44
+ $tracking_mode = 'analytics';
45
+ }
46
+ if ( $events_mode === false ) {
47
+ $events_mode = 'none';
48
+ }
49
+
50
+ if ( $update_mode === false ) {
51
+ $update_mode = 'none';
52
+ }
53
+
54
+ $count_b = 1;
55
+ if ( is_multisite() ) {
56
+ if ( function_exists( 'get_blog_count' ) ) {
57
+ $count_b = get_blog_count();
58
+ } else {
59
+ $count_b = 'Not Set';
60
+ }
61
+ }
62
+
63
+ $usesauth = 'No';
64
+ $local = MonsterInsights()->auth->is_authed();
65
+ $network = MonsterInsights()->auth->is_network_authed();
66
+
67
+ if ( $local && $network ) {
68
+ $usesauth = 'Both';
69
+ } else if ( $local ) {
70
+ $usesauth = 'Local';
71
+ } else if ( $network ) {
72
+ $usesauth = 'Network';
73
+ }
74
+
75
+ $data['php_version'] = phpversion();
76
+ $data['mi_version'] = MONSTERINSIGHTS_VERSION;
77
+ $data['wp_version'] = get_bloginfo( 'version' );
78
+ $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
79
+ $data['over_time'] = get_option( 'monsterinsights_over_time', array() );
80
+ $data['multisite'] = is_multisite();
81
+ $data['url'] = home_url();
82
+ $data['themename'] = $theme_data->Name;
83
+ $data['themeversion'] = $theme_data->Version;
84
+ $data['email'] = get_bloginfo( 'admin_email' );
85
+ $data['key'] = monsterinsights_get_license_key();
86
+ $data['sas'] = monsterinsights_get_shareasale_id();
87
+ $data['settings'] = monsterinsights_get_options();
88
+ $data['tracking_mode'] = $tracking_mode;
89
+ $data['events_mode'] = $events_mode;
90
+ $data['autoupdate'] = $update_mode;
91
+ $data['pro'] = (int) monsterinsights_is_pro_version();
92
+ $data['sites'] = $count_b;
93
+ $data['usagetracking'] = get_option( 'monsterinsights_usage_tracking_config', false );
94
+ $data['usercount'] = function_exists( 'get_user_count' ) ? get_user_count() : 'Not Set';
95
+ $data['usesauth'] = $usesauth;
96
+ $data['timezoneoffset']= date('P');
97
+ $data['installed_lite']= get_option( 'monsterinsights_installed_lite', array() );
98
+ $data['installed_pro'] = get_option( 'monsterinsights_installed_pro', array() );
99
+
100
+
101
+
102
+ // Retrieve current plugin information
103
+ if( ! function_exists( 'get_plugins' ) ) {
104
+ include ABSPATH . '/wp-admin/includes/plugin.php';
105
+ }
106
+
107
+ $plugins = array_keys( get_plugins() );
108
+ $active_plugins = get_option( 'active_plugins', array() );
109
+
110
+ foreach ( $plugins as $key => $plugin ) {
111
+ if ( in_array( $plugin, $active_plugins ) ) {
112
+ // Remove active plugins from list so we can show active and inactive separately
113
+ unset( $plugins[ $key ] );
114
+ }
115
+ }
116
+
117
+ $data['active_plugins'] = $active_plugins;
118
+ $data['inactive_plugins'] = $plugins;
119
+ $data['locale'] = get_locale();
120
+
121
+ return $data;
122
+ }
123
+
124
+ public function send_checkin( $override = false, $ignore_last_checkin = false ) {
125
+
126
+ $home_url = trailingslashit( home_url() );
127
+ if ( strpos( $home_url, 'monsterinsights.com' ) !== false ) {
128
+ return false;
129
+ }
130
+
131
+ if( ! $this->tracking_allowed() && ! $override ) {
132
+ return false;
133
+ }
134
+
135
+ // Send a maximum of once per week
136
+ $last_send = get_option( 'monsterinsights_usage_tracking_last_checkin' );
137
+ if ( is_numeric( $last_send ) && $last_send > strtotime( '-1 week' ) && ! $ignore_last_checkin ) {
138
+ return false;
139
+ }
140
+
141
+ $request = wp_remote_post( 'https://miusage.com/v1/checkin/', array(
142
+ 'method' => 'POST',
143
+ 'timeout' => 5,
144
+ 'redirection' => 5,
145
+ 'httpversion' => '1.1',
146
+ 'blocking' => false,
147
+ 'body' => $this->get_data(),
148
+ 'user-agent' => 'MI/' . MONSTERINSIGHTS_VERSION . '; ' . get_bloginfo( 'url' )
149
+ ) );
150
+
151
+ // If we have completed successfully, recheck in 1 week
152
+ update_option( 'monsterinsights_usage_tracking_last_checkin', time() );
153
+ return true;
154
+ }
155
+
156
+ private function tracking_allowed() {
157
+ return (bool) monsterinsights_get_option( 'anonymous_data', false ) || monsterinsights_is_pro_version();
158
+ }
159
+
160
+ public function schedule_send() {
161
+ if ( ! wp_next_scheduled( 'monsterinsights_usage_tracking_cron' ) ) {
162
+ $tracking = array();
163
+ $tracking['day'] = rand( 0, 6 );
164
+ $tracking['hour'] = rand( 0, 23 );
165
+ $tracking['minute'] = rand( 0, 59 );
166
+ $tracking['second'] = rand( 0, 59 );
167
+ $tracking['offset'] = ( $tracking['day'] * DAY_IN_SECONDS ) +
168
+ ( $tracking['hour'] * HOUR_IN_SECONDS ) +
169
+ ( $tracking['minute'] * MINUTE_IN_SECONDS ) +
170
+ $tracking['second'];
171
+ $tracking['initsend'] = strtotime("next sunday") + $tracking['offset'];
172
+
173
+ wp_schedule_event( $tracking['initsend'], 'weekly', 'monsterinsights_usage_tracking_cron' );
174
+ update_option( 'monsterinsights_usage_tracking_config', $tracking );
175
+ }
176
+ }
177
+
178
+ public function check_for_settings_optin() {
179
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
180
+ return;
181
+ }
182
+
183
+ if ( monsterinsights_is_pro_version() ) {
184
+ return;
185
+ }
186
+
187
+ // Send an intial check in on settings save
188
+ $anonymous_data = isset( $_POST['anonymous_data'] ) ? 1 : 0;
189
+ if ( $anonymous_data ) {
190
+ $this->send_checkin( true, true );
191
+ }
192
+
193
+ }
194
+
195
+ public function check_for_optin() {
196
+ if ( ! ( ! empty( $_REQUEST['mi_action'] ) && 'opt_into_tracking' === $_REQUEST['mi_action'] ) ) {
197
+ return;
198
+ }
199
+
200
+ if ( monsterinsights_get_option( 'anonymous_data', false ) ) {
201
+ return;
202
+ }
203
+
204
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
205
+ return;
206
+ }
207
+
208
+ if ( monsterinsights_is_pro_version() ) {
209
+ return;
210
+ }
211
+
212
+ monsterinsights_update_option( 'anonymous_data', 1 );
213
+ $this->send_checkin( true, true );
214
+ update_option( 'monsterinsights_tracking_notice', 1 );
215
+ }
216
+
217
+ public function check_for_optout() {
218
+ if ( ! ( ! empty( $_REQUEST['mi_action'] ) && 'opt_out_of_tracking' === $_REQUEST['mi_action'] ) ) {
219
+ return;
220
+ }
221
+
222
+ if ( monsterinsights_get_option( 'anonymous_data', false ) ) {
223
+ return;
224
+ }
225
+
226
+ if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
227
+ return;
228
+ }
229
+
230
+ if ( monsterinsights_is_pro_version() ) {
231
+ return;
232
+ }
233
+
234
+ monsterinsights_update_option( 'anonymous_data', 0 );
235
+ update_option( 'monsterinsights_tracking_notice', 1 );
236
+ }
237
+
238
+ public function add_schedules( $schedules = array() ) {
239
+ // Adds once weekly to the existing schedules.
240
+ $schedules['weekly'] = array(
241
+ 'interval' => 604800,
242
+ 'display' => __( 'Once Weekly', 'google-analytics-for-wordpress' )
243
+ );
244
+ return $schedules;
245
+ }
246
+ }
247
  new MonsterInsights_Tracking();
includes/api-request.php CHANGED
@@ -1,439 +1,439 @@
1
- <?php
2
- /**
3
- * API Request class.
4
- *
5
- * @since 7.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
- final class MonsterInsights_API_Request {
11
-
12
- /**
13
- * Base API route.
14
- *
15
- * @since 7.0.0
16
- *
17
- * @var string
18
- */
19
- public $base = 'api.monsterinsights.com/v2/';
20
-
21
- /**
22
- * Current API route.
23
- *
24
- * @since 7.0.0
25
- *
26
- * @var bool|string
27
- */
28
- public $route = false;
29
-
30
- /**
31
- * Full API URL endpoint.
32
- *
33
- * @since 7.0.0
34
- *
35
- * @var bool|string
36
- */
37
- public $url = false;
38
-
39
- /**
40
- * Current API method.
41
- *
42
- * @since 7.0.0
43
- *
44
- * @var bool|string
45
- */
46
- public $method = false;
47
-
48
- /**
49
- * Is a network request.
50
- *
51
- * @since 7.2.0
52
- *
53
- * @var bool
54
- */
55
- public $network = false;
56
-
57
- /**
58
- * API token.
59
- *
60
- * @since 7.0.0
61
- *
62
- * @var bool|string
63
- */
64
- public $token = false;
65
-
66
- /**
67
- * API Key.
68
- *
69
- * @since 7.0.0
70
- *
71
- * @var bool|string
72
- */
73
- public $key = false;
74
-
75
- /**
76
- * API tt.
77
- *
78
- * @since 7.0.0
79
- *
80
- * @var bool|string
81
- */
82
- public $tt = false;
83
-
84
- /**
85
- * API return.
86
- *
87
- * @since 7.0.0
88
- *
89
- * @var bool|string
90
- */
91
- public $return = false;
92
-
93
- /**
94
- * Start date.
95
- *
96
- * @since 7.0.0
97
- *
98
- * @var string
99
- */
100
- public $start = '';
101
-
102
- /**
103
- * End Date.
104
- *
105
- * @since 7.0.0
106
- *
107
- * @var string
108
- */
109
- public $end = '';
110
-
111
- /**
112
- * Plugin slug.
113
- *
114
- * @since 7.0.0
115
- *
116
- * @var bool|string
117
- */
118
- public $plugin = false;
119
-
120
- /**
121
- * URL to test connection with.
122
- *
123
- * @since 7.3.2
124
- *
125
- * @var string
126
- */
127
- public $testurl = '';
128
-
129
- /**
130
- * Additional data to add to request body
131
- *
132
- * @since 7.0.0
133
- *
134
- * @var array
135
- */
136
- protected $additional_data = array();
137
-
138
- /**
139
- * Primary class constructor.
140
- *
141
- * @since 7.0.0
142
- *
143
- * @param string $route The API route to target.
144
- * @param array $args Array of API credentials.
145
- * @param string $method The API method.
146
- */
147
- public function __construct( $route, $args, $method = 'POST' ) {
148
-
149
- // Set class properties.
150
- $this->base = trailingslashit( monsterinsights_get_api_url() );
151
- $this->route = $route;
152
- $this->protocol = 'https://';
153
- $this->url = trailingslashit( $this->protocol . $this->base . $this->route );
154
- $this->method = $method;
155
- $this->network = is_network_admin() || ! empty( $args['network'] );
156
-
157
- $default_token = $this->network ? MonsterInsights()->auth->get_network_token() : MonsterInsights()->auth->get_token();
158
- $default_key = $this->network ? MonsterInsights()->auth->get_network_key() : MonsterInsights()->auth->get_key();
159
-
160
- $this->token = ! empty( $args['token'] ) ? $args['token'] : $default_token;
161
- $this->key = ! empty( $args['key'] ) ? $args['key'] : $default_key;
162
- $this->tt = ! empty( $args['tt'] ) ? $args['tt'] : '';
163
- $this->return = ! empty( $args['return'] ) ? $args['return'] : '';
164
- $this->start = ! empty( $args['start'] ) ? $args['start'] : '';
165
- $this->end = ! empty( $args['end'] ) ? $args['end'] : '';
166
-
167
- // We need to do this hack so that the network panel + the site_url of the main site are distinct
168
- $this->site_url = is_network_admin() ? network_admin_url() : site_url();
169
-
170
- if ( monsterinsights_is_pro_version() ) {
171
- $this->license = $this->network ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
172
- }
173
- $this->plugin = MonsterInsights()->plugin_slug;
174
- $this->miversion = MONSTERINSIGHTS_VERSION;
175
- $this->sitei = ! empty( $args['sitei'] ) ? $args['sitei'] : '';
176
- $this->testurl = ! empty( $args['testurl'] ) ? $args['testurl'] : '';
177
- }
178
-
179
- /**
180
- * Processes the API request.
181
- *
182
- * @since 7.0.0
183
- *
184
- * @return mixed $value The response to the API call.
185
- */
186
- public function request() {
187
- // Make sure we're not blocked
188
- $blocked = $this->is_blocked( $this->url );
189
- if ( $blocked || is_wp_error( $blocked ) ) {
190
- if ( is_wp_error( $blocked ) ) {
191
- return new WP_Error( 'api-error', sprintf( __( 'The firewall of your server is blocking outbound calls. Please contact your hosting provider to fix this issue. %s', 'google-analytics-for-wordpress' ), $blocked->get_error_message() ) );
192
- } else {
193
- return new WP_Error( 'api-error', __( 'The firewall of your server is blocking outbound calls. Please contact your hosting provider to fix this issue.', 'google-analytics-for-wordpress' ) );
194
- }
195
- }
196
-
197
- // Build the body of the request.
198
- $body = array();
199
-
200
- if ( ! empty( $this->token ) ) {
201
- $body['token'] = $this->token;
202
- }
203
-
204
- if ( ! empty( $this->key ) ) {
205
- $body['key'] = $this->key;
206
- }
207
-
208
- if ( ! empty( $this->tt ) ) {
209
- $body['tt'] = $this->tt;
210
- }
211
-
212
- if ( ! empty( $this->return ) ) {
213
- $body['return'] = $this->return;
214
- }
215
-
216
- if ( monsterinsights_is_pro_version() && ! empty( $this->license ) ) {
217
- $body['license'] = $this->license;
218
- }
219
-
220
- if ( ! empty( $this->start ) ) {
221
- $body['start'] = $this->start;
222
- }
223
-
224
- if ( ! empty( $this->end ) ) {
225
- $body['end'] = $this->end;
226
- }
227
-
228
- if ( ! empty( $this->sitei ) ) {
229
- $body['sitei'] = $this->sitei;
230
- }
231
-
232
- $body['siteurl'] = $this->site_url;
233
- $body['miversion'] = $this->miversion;
234
-
235
- // If a plugin API request, add the data.
236
- if ( 'info' == $this->route || 'update' == $this->route ) {
237
- $body['miapi-plugin'] = $this->plugin;
238
- }
239
-
240
- // Add in additional data if needed.
241
- if ( ! empty( $this->additional_data ) ) {
242
- $body['miapi-data'] = maybe_serialize( $this->additional_data );
243
- }
244
-
245
- if ( 'GET' == $this->method ) {
246
- $body['time'] = time(); // just to avoid caching
247
- }
248
-
249
- $body['timezone'] = date('e');
250
-
251
- $body['network'] = $this->network ? 'network' : 'site';
252
-
253
- $body['ip'] = ! empty( $_SERVER['SERVER_ADDR'] ) ? $_SERVER['SERVER_ADDR'] : '';
254
-
255
- // This filter will be removed in the future.
256
- $body = apply_filters( 'monsterinsights_api_request_body', $body );
257
-
258
- $string = http_build_query( $body, '', '&' );
259
-
260
- // Build the headers of the request.
261
- $headers = array(
262
- 'Content-Type' => 'application/x-www-form-urlencoded',
263
- 'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0',
264
- 'Pragma' => 'no-cache',
265
- 'Expires' => 0,
266
- 'MIAPI-Referer' => is_network_admin() ? network_admin_url() : site_url(),
267
- 'MIAPI-Sender' => 'WordPress',
268
- );
269
-
270
- //if ( $this->apikey ) {
271
- // $headers['X-MonsterInsights-ApiKey'] = $this->apikey;
272
- //}
273
-
274
- // Setup data to be sent to the API.
275
- $data = array(
276
- 'headers' => $headers,
277
- 'body' => $body,
278
- 'timeout' => 3000,
279
- 'user-agent' => 'MI/' . MONSTERINSIGHTS_VERSION . '; ' . $this->site_url,
280
- 'sslverify' => false
281
- );
282
-
283
- // Perform the query and retrieve the response.
284
- $response = 'GET' == $this->method ? wp_remote_get( esc_url_raw( $this->url ) . '?' . $string, $data ) : wp_remote_post( esc_url_raw( $this->url ), $data );
285
-
286
- //return new WP_Error( 'debug', '<pre>' . var_export( $response, true ) . '</pre>' );
287
-
288
- if ( is_wp_error( $response ) ) {
289
- return $response;
290
- }
291
-
292
- $response_code = wp_remote_retrieve_response_code( $response );
293
- $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
294
- //return new WP_Error( 'debug', '<pre>' . var_export( $response_body, true ) . '</pre>' );
295
- //var_dump( $response_body );
296
- // Bail out early if there are any errors.
297
- if ( is_wp_error( $response_body ) ) {
298
- return $response_body;
299
- }
300
-
301
- // If not a 200 status header, send back error.
302
- if ( 200 != $response_code ) {
303
- $type = ! empty( $response_body['type'] ) ? $response_body['type'] : 'api-error';
304
-
305
- if ( empty( $response_code ) ) {
306
- return new WP_Error( $type, __( 'The API was unreachable.', 'google-analytics-for-wordpress' ) );
307
- }
308
-
309
- if ( empty( $response_body ) || ( empty( $response_body['message'] ) && empty( $response_body['error'] ) ) ) {
310
- return new WP_Error( $type, sprintf( __( 'The API returned a <strong>%s</strong> response', 'google-analytics-for-wordpress' ), $response_code ) );
311
- }
312
-
313
- if ( ! empty( $response_body['message'] ) ) {
314
- return new WP_Error( $type, sprintf( __( 'The API returned a <strong>%d</strong> response with this message: <strong>%s</strong>', 'google-analytics-for-wordpress' ), $response_code, stripslashes( $response_body['message'] ) ) );
315
- }
316
-
317
- if ( ! empty( $response_body['error'] ) ) {
318
- return new WP_Error( $type, sprintf( __( 'The API returned a <strong>%d</strong> response with this message: <strong>%s</strong>', 'google-analytics-for-wordpress' ), $response_code, stripslashes( $response_body['error'] ) ) );
319
- }
320
- }
321
-
322
- // If TT required
323
- if ( ! empty( $this->tt ) ) {
324
- if ( empty( $response_body['tt'] ) || ! hash_equals( $this->tt, $response_body['tt'] ) ) {
325
- // TT isn't set on return or doesn't match
326
- return new WP_Error( 'validation-error', sprintf( __( 'Improper API request.', 'google-analytics-for-wordpress' ) ) );
327
- }
328
- }
329
-
330
- // Return the json decoded content.
331
- return $response_body;
332
- }
333
-
334
- /**
335
- * Sets a class property.
336
- *
337
- * @since 7.0.0
338
- *
339
- * @param string $key The property to set.
340
- * @param string $val The value to set for the property.
341
- * @return mixed $value The response to the API call.
342
- */
343
- public function set( $key, $val ) {
344
- $this->{$key} = $val;
345
- }
346
-
347
- /**
348
- * Allow additional data to be passed in the request
349
- *
350
- * @since 7.0.0
351
- *
352
- * @param array $data
353
- * return void
354
- */
355
- public function set_additional_data( array $data ) {
356
- $this->additional_data = array_merge( $this->additional_data, $data );
357
- }
358
-
359
- /**
360
- * Checks for SSL for making API requests.
361
- *
362
- * @since 7.0.0
363
- *
364
- * return bool True if SSL is enabled, false otherwise.
365
- */
366
- public function is_ssl() {
367
- // Use the base is_ssl check first.
368
- if ( is_ssl() ) {
369
- return true;
370
- } else if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
371
- // Also catch proxies and load balancers.
372
- return true;
373
- } else if ( defined( 'FORCE_SSL_ADMIN' ) && FORCE_SSL_ADMIN ) {
374
- return true;
375
- }
376
-
377
- // Otherwise, return false.
378
- return false;
379
- }
380
-
381
- private function is_blocked( $url = '' ) {
382
- global $Airplane_Mode_Core;
383
- if ( defined( 'AIRMDE_VER' ) && ! empty( $Airplane_Mode_Core ) && $Airplane_Mode_Core->enabled() ) {
384
- return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the Airplane Mode plugin is active.', 'google-analytics-for-wordpress' ) );
385
- }
386
-
387
- // The below page is a testing empty content HTML page used for firewall/router login detection
388
- // and for image linking purposes in Google Images. We use it to test outbound connections since it is run on google.com
389
- // and is only a few bytes large. Plus on Google's main CDN so it loads in most places in 0.07 seconds or less. Perfect for our
390
- // use case of quickly testing outbound connections.
391
- $testurl = ! empty( $this->testurl ) ? $this->testurl :'http://www.google.com/blank.html';
392
- if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) {
393
- if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
394
- $wp_http = new WP_Http();
395
- $on_blacklist = $wp_http->block_request( $url );
396
- if ( $on_blacklist ) {
397
- return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the API url is on the WP HTTP blocklist.', 'google-analytics-for-wordpress' ) );
398
- } else {
399
- $params = array(
400
- 'sslverify' => false,
401
- 'timeout' => 2,
402
- 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,
403
- 'body' => ''
404
- );
405
- $response = wp_remote_get( $testurl, $params );
406
- if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
407
- return false;
408
- } else {
409
- if ( is_wp_error( $response ) ) {
410
- return $response;
411
- } else {
412
- return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the call to Google failed.', 'google-analytics-for-wordpress' ) );
413
- }
414
- }
415
- }
416
- } else {
417
- return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because no external hosts are allowed on this site.', 'google-analytics-for-wordpress' ) );
418
- }
419
- } else {
420
- $params = array(
421
- 'sslverify' => false,
422
- 'timeout' => 2,
423
- 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,
424
- 'body' => ''
425
- );
426
- $response = wp_remote_get( $testurl, $params );
427
-
428
- if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
429
- return false;
430
- } else {
431
- if ( is_wp_error( $response ) ) {
432
- return $response;
433
- } else {
434
- return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the call to Google failed.', 'google-analytics-for-wordpress' ) );
435
- }
436
- }
437
- }
438
- }
439
  }
1
+ <?php
2
+ /**
3
+ * API Request class.
4
+ *
5
+ * @since 7.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+ final class MonsterInsights_API_Request {
11
+
12
+ /**
13
+ * Base API route.
14
+ *
15
+ * @since 7.0.0
16
+ *
17
+ * @var string
18
+ */
19
+ public $base = 'api.monsterinsights.com/v2/';
20
+
21
+ /**
22
+ * Current API route.
23
+ *
24
+ * @since 7.0.0
25
+ *
26
+ * @var bool|string
27
+ */
28
+ public $route = false;
29
+
30
+ /**
31
+ * Full API URL endpoint.
32
+ *
33
+ * @since 7.0.0
34
+ *
35
+ * @var bool|string
36
+ */
37
+ public $url = false;
38
+
39
+ /**
40
+ * Current API method.
41
+ *
42
+ * @since 7.0.0
43
+ *
44
+ * @var bool|string
45
+ */
46
+ public $method = false;
47
+
48
+ /**
49
+ * Is a network request.
50
+ *
51
+ * @since 7.2.0
52
+ *
53
+ * @var bool
54
+ */
55
+ public $network = false;
56
+
57
+ /**
58
+ * API token.
59
+ *
60
+ * @since 7.0.0
61
+ *
62
+ * @var bool|string
63
+ */
64
+ public $token = false;
65
+
66
+ /**
67
+ * API Key.
68
+ *
69
+ * @since 7.0.0
70
+ *
71
+ * @var bool|string
72
+ */
73
+ public $key = false;
74
+
75
+ /**
76
+ * API tt.
77
+ *
78
+ * @since 7.0.0
79
+ *
80
+ * @var bool|string
81
+ */
82
+ public $tt = false;
83
+
84
+ /**
85
+ * API return.
86
+ *
87
+ * @since 7.0.0
88
+ *
89
+ * @var bool|string
90
+ */
91
+ public $return = false;
92
+
93
+ /**
94
+ * Start date.
95
+ *
96
+ * @since 7.0.0
97
+ *
98
+ * @var string
99
+ */
100
+ public $start = '';
101
+
102
+ /**
103
+ * End Date.
104
+ *
105
+ * @since 7.0.0
106
+ *
107
+ * @var string
108
+ */
109
+ public $end = '';
110
+
111
+ /**
112
+ * Plugin slug.
113
+ *
114
+ * @since 7.0.0
115
+ *
116
+ * @var bool|string
117
+ */
118
+ public $plugin = false;
119
+
120
+ /**
121
+ * URL to test connection with.
122
+ *
123
+ * @since 7.3.2
124
+ *
125
+ * @var string
126
+ */
127
+ public $testurl = '';
128
+
129
+ /**
130
+ * Additional data to add to request body
131
+ *
132
+ * @since 7.0.0
133
+ *
134
+ * @var array
135
+ */
136
+ protected $additional_data = array();
137
+
138
+ /**
139
+ * Primary class constructor.
140
+ *
141
+ * @since 7.0.0
142
+ *
143
+ * @param string $route The API route to target.
144
+ * @param array $args Array of API credentials.
145
+ * @param string $method The API method.
146
+ */
147
+ public function __construct( $route, $args, $method = 'POST' ) {
148
+
149
+ // Set class properties.
150
+ $this->base = trailingslashit( monsterinsights_get_api_url() );
151
+ $this->route = $route;
152
+ $this->protocol = 'https://';
153
+ $this->url = trailingslashit( $this->protocol . $this->base . $this->route );
154
+ $this->method = $method;
155
+ $this->network = is_network_admin() || ! empty( $args['network'] );
156
+
157
+ $default_token = $this->network ? MonsterInsights()->auth->get_network_token() : MonsterInsights()->auth->get_token();
158
+ $default_key = $this->network ? MonsterInsights()->auth->get_network_key() : MonsterInsights()->auth->get_key();
159
+
160
+ $this->token = ! empty( $args['token'] ) ? $args['token'] : $default_token;
161
+ $this->key = ! empty( $args['key'] ) ? $args['key'] : $default_key;
162
+ $this->tt = ! empty( $args['tt'] ) ? $args['tt'] : '';
163
+ $this->return = ! empty( $args['return'] ) ? $args['return'] : '';
164
+ $this->start = ! empty( $args['start'] ) ? $args['start'] : '';
165
+ $this->end = ! empty( $args['end'] ) ? $args['end'] : '';
166
+
167
+ // We need to do this hack so that the network panel + the site_url of the main site are distinct
168
+ $this->site_url = is_network_admin() ? network_admin_url() : site_url();
169
+
170
+ if ( monsterinsights_is_pro_version() ) {
171
+ $this->license = $this->network ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
172
+ }
173
+ $this->plugin = MonsterInsights()->plugin_slug;
174
+ $this->miversion = MONSTERINSIGHTS_VERSION;
175
+ $this->sitei = ! empty( $args['sitei'] ) ? $args['sitei'] : '';
176
+ $this->testurl = ! empty( $args['testurl'] ) ? $args['testurl'] : '';
177
+ }
178
+
179
+ /**
180
+ * Processes the API request.
181
+ *
182
+ * @since 7.0.0
183
+ *
184
+ * @return mixed $value The response to the API call.
185
+ */
186
+ public function request() {
187
+ // Make sure we're not blocked
188
+ $blocked = $this->is_blocked( $this->url );
189
+ if ( $blocked || is_wp_error( $blocked ) ) {
190
+ if ( is_wp_error( $blocked ) ) {
191
+ return new WP_Error( 'api-error', sprintf( __( 'The firewall of your server is blocking outbound calls. Please contact your hosting provider to fix this issue. %s', 'google-analytics-for-wordpress' ), $blocked->get_error_message() ) );
192
+ } else {
193
+ return new WP_Error( 'api-error', __( 'The firewall of your server is blocking outbound calls. Please contact your hosting provider to fix this issue.', 'google-analytics-for-wordpress' ) );
194
+ }
195
+ }
196
+
197
+ // Build the body of the request.
198
+ $body = array();
199
+
200
+ if ( ! empty( $this->token ) ) {
201
+ $body['token'] = $this->token;
202
+ }
203
+
204
+ if ( ! empty( $this->key ) ) {
205
+ $body['key'] = $this->key;
206
+ }
207
+
208
+ if ( ! empty( $this->tt ) ) {
209
+ $body['tt'] = $this->tt;
210
+ }
211
+
212
+ if ( ! empty( $this->return ) ) {
213
+ $body['return'] = $this->return;
214
+ }
215
+
216
+ if ( monsterinsights_is_pro_version() && ! empty( $this->license ) ) {
217
+ $body['license'] = $this->license;
218
+ }
219
+
220
+ if ( ! empty( $this->start ) ) {
221
+ $body['start'] = $this->start;
222
+ }
223
+
224
+ if ( ! empty( $this->end ) ) {
225
+ $body['end'] = $this->end;
226
+ }
227
+
228
+ if ( ! empty( $this->sitei ) ) {
229
+ $body['sitei'] = $this->sitei;
230
+ }
231
+
232
+ $body['siteurl'] = $this->site_url;
233
+ $body['miversion'] = $this->miversion;
234
+
235
+ // If a plugin API request, add the data.
236
+ if ( 'info' == $this->route || 'update' == $this->route ) {
237
+ $body['miapi-plugin'] = $this->plugin;
238
+ }
239
+
240
+ // Add in additional data if needed.
241
+ if ( ! empty( $this->additional_data ) ) {
242
+ $body['miapi-data'] = maybe_serialize( $this->additional_data );
243
+ }
244
+
245
+ if ( 'GET' == $this->method ) {
246
+ $body['time'] = time(); // just to avoid caching
247
+ }
248
+
249
+ $body['timezone'] = date('e');
250
+
251
+ $body['network'] = $this->network ? 'network' : 'site';
252
+
253
+ $body['ip'] = ! empty( $_SERVER['SERVER_ADDR'] ) ? $_SERVER['SERVER_ADDR'] : '';
254
+
255
+ // This filter will be removed in the future.
256
+ $body = apply_filters( 'monsterinsights_api_request_body', $body );
257
+
258
+ $string = http_build_query( $body, '', '&' );
259
+
260
+ // Build the headers of the request.
261
+ $headers = array(
262
+ 'Content-Type' => 'application/x-www-form-urlencoded',
263
+ 'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0',
264
+ 'Pragma' => 'no-cache',
265
+ 'Expires' => 0,
266
+ 'MIAPI-Referer' => is_network_admin() ? network_admin_url() : site_url(),
267
+ 'MIAPI-Sender' => 'WordPress',
268
+ );
269
+
270
+ //if ( $this->apikey ) {
271
+ // $headers['X-MonsterInsights-ApiKey'] = $this->apikey;
272
+ //}
273
+
274
+ // Setup data to be sent to the API.
275
+ $data = array(
276
+ 'headers' => $headers,
277
+ 'body' => $body,
278
+ 'timeout' => 3000,
279
+ 'user-agent' => 'MI/' . MONSTERINSIGHTS_VERSION . '; ' . $this->site_url,
280
+ 'sslverify' => false
281
+ );
282
+
283
+ // Perform the query and retrieve the response.
284
+ $response = 'GET' == $this->method ? wp_remote_get( esc_url_raw( $this->url ) . '?' . $string, $data ) : wp_remote_post( esc_url_raw( $this->url ), $data );
285
+
286
+ //return new WP_Error( 'debug', '<pre>' . var_export( $response, true ) . '</pre>' );
287
+
288
+ if ( is_wp_error( $response ) ) {
289
+ return $response;
290
+ }
291
+
292
+ $response_code = wp_remote_retrieve_response_code( $response );
293
+ $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
294
+ //return new WP_Error( 'debug', '<pre>' . var_export( $response_body, true ) . '</pre>' );
295
+ //var_dump( $response_body );
296
+ // Bail out early if there are any errors.
297
+ if ( is_wp_error( $response_body ) ) {
298
+ return $response_body;
299
+ }
300
+
301
+ // If not a 200 status header, send back error.
302
+ if ( 200 != $response_code ) {
303
+ $type = ! empty( $response_body['type'] ) ? $response_body['type'] : 'api-error';
304
+
305
+ if ( empty( $response_code ) ) {
306
+ return new WP_Error( $type, __( 'The API was unreachable.', 'google-analytics-for-wordpress' ) );
307
+ }
308
+
309
+ if ( empty( $response_body ) || ( empty( $response_body['message'] ) && empty( $response_body['error'] ) ) ) {
310
+ return new WP_Error( $type, sprintf( __( 'The API returned a <strong>%s</strong> response', 'google-analytics-for-wordpress' ), $response_code ) );
311
+ }
312
+
313
+ if ( ! empty( $response_body['message'] ) ) {
314
+ return new WP_Error( $type, sprintf( __( 'The API returned a <strong>%d</strong> response with this message: <strong>%s</strong>', 'google-analytics-for-wordpress' ), $response_code, stripslashes( $response_body['message'] ) ) );
315
+ }
316
+
317
+ if ( ! empty( $response_body['error'] ) ) {
318
+ return new WP_Error( $type, sprintf( __( 'The API returned a <strong>%d</strong> response with this message: <strong>%s</strong>', 'google-analytics-for-wordpress' ), $response_code, stripslashes( $response_body['error'] ) ) );
319
+ }
320
+ }
321
+
322
+ // If TT required
323
+ if ( ! empty( $this->tt ) ) {
324
+ if ( empty( $response_body['tt'] ) || ! hash_equals( $this->tt, $response_body['tt'] ) ) {
325
+ // TT isn't set on return or doesn't match
326
+ return new WP_Error( 'validation-error', sprintf( __( 'Improper API request.', 'google-analytics-for-wordpress' ) ) );
327
+ }
328
+ }
329
+
330
+ // Return the json decoded content.
331
+ return $response_body;
332
+ }
333
+
334
+ /**
335
+ * Sets a class property.
336
+ *
337
+ * @since 7.0.0
338
+ *
339
+ * @param string $key The property to set.
340
+ * @param string $val The value to set for the property.
341
+ * @return mixed $value The response to the API call.
342
+ */
343
+ public function set( $key, $val ) {
344
+ $this->{$key} = $val;
345
+ }
346
+
347
+ /**
348
+ * Allow additional data to be passed in the request
349
+ *
350
+ * @since 7.0.0
351
+ *
352
+ * @param array $data
353
+ * return void
354
+ */
355
+ public function set_additional_data( array $data ) {
356
+ $this->additional_data = array_merge( $this->additional_data, $data );
357
+ }
358
+
359
+ /**
360
+ * Checks for SSL for making API requests.
361
+ *
362
+ * @since 7.0.0
363
+ *
364
+ * return bool True if SSL is enabled, false otherwise.
365
+ */
366
+ public function is_ssl() {
367
+ // Use the base is_ssl check first.
368
+ if ( is_ssl() ) {
369
+ return true;
370
+ } else if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
371
+ // Also catch proxies and load balancers.
372
+ return true;
373
+ } else if ( defined( 'FORCE_SSL_ADMIN' ) && FORCE_SSL_ADMIN ) {
374
+ return true;
375
+ }
376
+
377
+ // Otherwise, return false.
378
+ return false;
379
+ }
380
+
381
+ private function is_blocked( $url = '' ) {
382
+ global $Airplane_Mode_Core;
383
+ if ( defined( 'AIRMDE_VER' ) && ! empty( $Airplane_Mode_Core ) && $Airplane_Mode_Core->enabled() ) {
384
+ return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the Airplane Mode plugin is active.', 'google-analytics-for-wordpress' ) );
385
+ }
386
+
387
+ // The below page is a testing empty content HTML page used for firewall/router login detection
388
+ // and for image linking purposes in Google Images. We use it to test outbound connections since it is run on google.com
389
+ // and is only a few bytes large. Plus on Google's main CDN so it loads in most places in 0.07 seconds or less. Perfect for our
390
+ // use case of quickly testing outbound connections.
391
+ $testurl = ! empty( $this->testurl ) ? $this->testurl :'http://www.google.com/blank.html';
392
+ if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) {
393
+ if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
394
+ $wp_http = new WP_Http();
395
+ $on_blacklist = $wp_http->block_request( $url );
396
+ if ( $on_blacklist ) {
397
+ return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the API url is on the WP HTTP blocklist.', 'google-analytics-for-wordpress' ) );
398
+ } else {
399
+ $params = array(
400
+ 'sslverify' => false,
401
+ 'timeout' => 2,
402
+ 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,
403
+ 'body' => ''
404
+ );
405
+ $response = wp_remote_get( $testurl, $params );
406
+ if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
407
+ return false;
408
+ } else {
409
+ if ( is_wp_error( $response ) ) {
410
+ return $response;
411
+ } else {
412
+ return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the call to Google failed.', 'google-analytics-for-wordpress' ) );
413
+ }
414
+ }
415
+ }
416
+ } else {
417
+ return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because no external hosts are allowed on this site.', 'google-analytics-for-wordpress' ) );
418
+ }
419
+ } else {
420
+ $params = array(
421
+ 'sslverify' => false,
422
+ 'timeout' => 2,
423
+ 'user-agent' => 'MonsterInsights/' . MONSTERINSIGHTS_VERSION,
424
+ 'body' => ''
425
+ );
426
+ $response = wp_remote_get( $testurl, $params );
427
+
428
+ if( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 ) {
429
+ return false;
430
+ } else {
431
+ if ( is_wp_error( $response ) ) {
432
+ return $response;
433
+ } else {
434
+ return new WP_Error( 'api-error', __( 'Reason: The API was unreachable because the call to Google failed.', 'google-analytics-for-wordpress' ) );
435
+ }
436
+ }
437
+ }
438
+ }
439
  }
includes/auth.php CHANGED
@@ -1,243 +1,250 @@
1
- <?php
2
- /**
3
- * Auth class.
4
- *
5
- * Helper for auth.
6
- *
7
- * @since 7.0.0
8
- *
9
- * @package MonsterInsights
10
- * @subpackage Auth
11
- * @author Chris Christoff
12
- */
13
-
14
- // Exit if accessed directly
15
- if ( ! defined( 'ABSPATH' ) ) {
16
- exit;
17
- }
18
-
19
- final class MonsterInsights_Auth {
20
-
21
- private $profile = array();
22
- private $network = array();
23
-
24
- /**
25
- * Primary class constructor.
26
- *
27
- * @access public
28
- * @since 7.0.0
29
- */
30
- public function __construct() {
31
- $this->profile = $this->get_analytics_profile();
32
- $this->network = $this->get_network_analytics_profile();
33
- }
34
-
35
- public function is_manual() {
36
- return ! empty( $this->profile['manual'] );
37
- }
38
- public function is_network_manual() {
39
- return ! empty( $this->network['manual'] );
40
- }
41
-
42
- public function is_authed() {
43
- return ! empty( $this->profile['key'] );
44
- }
45
-
46
- public function is_network_authed() {
47
- return ! empty( $this->network['key'] );
48
- }
49
-
50
- public function get_analytics_profile( $force = false ) {
51
- if ( ! empty( $this->profile ) && ! $force ) {
52
- return $this->profile;
53
- } else {
54
- $profile = get_option( 'monsterinsights_site_profile', array() );
55
- $this->profile = $profile;
56
- return $profile;
57
- }
58
- }
59
-
60
- public function get_network_analytics_profile( $force = false ) {
61
- if ( ! empty( $this->network ) && ! $force ) {
62
- return $this->network;
63
- } else {
64
- $profile = get_site_option( 'monsterinsights_network_profile', array() );
65
- $this->network = $profile;
66
- return $profile;
67
- }
68
- }
69
-
70
- public function set_analytics_profile( $data = array() ){
71
- update_option( 'monsterinsights_site_profile', $data );
72
- $this->profile = $data;
73
- }
74
-
75
- public function set_network_analytics_profile( $data = array() ){
76
- update_site_option( 'monsterinsights_network_profile', $data );
77
- $this->network = $data;
78
- }
79
-
80
- public function delete_analytics_profile( $migrate = true ){
81
- if ( $migrate ) {
82
- $newdata = array();
83
- if ( isset( $this->profile['ua'] ) ) {
84
- $newdata['manual'] = $this->profile['ua'];
85
- }
86
- $this->profile = $newdata;
87
- $this->set_analytics_profile( $newdata );
88
- } else {
89
- $this->profile = array();
90
- delete_option( 'monsterinsights_site_profile' );
91
- }
92
- }
93
-
94
- public function delete_network_analytics_profile( $migrate = true ){
95
- if ( $migrate ) {
96
- $newdata = array();
97
- if ( isset( $this->network['ua'] ) ) {
98
- $newdata['manual'] = $this->network['ua'];
99
- }
100
- $this->network = $newdata;
101
- $this->set_network_analytics_profile( $newdata );
102
- } else {
103
- $this->network = array();
104
- delete_site_option( 'monsterinsights_network_profile' );
105
- }
106
- }
107
-
108
- public function set_manual_ua( $ua = '' ) {
109
- if ( empty( $ua ) ) {
110
- return;
111
- }
112
-
113
- if ( $this->is_authed() ) {
114
- MonsterInsights()->api_auth->delete_auth();
115
- }
116
-
117
- $data = array();
118
- if ( empty( $this->profile ) ) {
119
- $data['manual'] = $ua;
120
- } else {
121
- $data = $this->profile;
122
- $data['manual'] = $ua;
123
- }
124
-
125
- do_action( 'monsterinsights_reports_delete_aggregate_data' );
126
-
127
- $this->profile = $data;
128
- $this->set_analytics_profile( $data );
129
- }
130
-
131
- public function set_network_manual_ua( $ua = '' ) {
132
- if ( empty( $ua ) ) {
133
- return;
134
- }
135
-
136
- if ( $this->is_network_authed() ) {
137
- MonsterInsights()->api_auth->delete_auth();
138
- }
139
-
140
- $data = array();
141
- if ( empty( $this->network ) ) {
142
- $data['manual'] = $ua;
143
- } else {
144
- $data = $this->network;
145
- $data['manual'] = $ua;
146
- }
147
-
148
- do_action( 'monsterinsights_reports_delete_network_aggregate_data' );
149
-
150
- $this->network = $data;
151
- $this->set_network_analytics_profile( $data );
152
- }
153
-
154
- public function delete_manual_ua() {
155
- if ( ! empty( $this->profile ) && ! empty( $this->profile['manual'] ) ) {
156
- unset( $this->profile['manual'] );
157
- $this->set_analytics_profile( $this->profile );
158
- }
159
- }
160
-
161
- public function delete_network_manual_ua() {
162
- if ( ! empty( $this->network ) && ! empty( $this->network['manual'] ) ) {
163
- unset( $this->network['manual'] );
164
- $this->set_network_analytics_profile( $this->network );
165
- }
166
- }
167
-
168
- public function get_manual_ua() {
169
- return ! empty( $this->profile['manual'] ) ? monsterinsights_is_valid_ua( $this->profile['manual'] ) : '';
170
- }
171
-
172
- public function get_network_manual_ua() {
173
- return ! empty( $this->network['manual'] ) ? monsterinsights_is_valid_ua( $this->network['manual'] ) : '';
174
- }
175
-
176
- public function get_ua() {
177
- return ! empty( $this->profile['ua'] ) ? monsterinsights_is_valid_ua( $this->profile['ua'] ) : '';
178
- }
179
-
180
- public function get_network_ua() {
181
- return ! empty( $this->network['ua'] ) ? monsterinsights_is_valid_ua( $this->network['ua'] ) : '';
182
- }
183
-
184
- public function get_viewname(){
185
- return ! empty( $this->profile['viewname'] ) ? $this->profile['viewname'] : '';
186
- }
187
-
188
- public function get_network_viewname(){
189
- return ! empty( $this->network['viewname'] ) ? $this->network['viewname'] : '';
190
- }
191
-
192
- public function get_accountid(){
193
- return ! empty( $this->profile['a'] ) ? $this->profile['a'] : '';
194
- }
195
-
196
- public function get_network_accountid(){
197
- return ! empty( $this->network['a'] ) ? $this->network['a'] : '';
198
- }
199
-
200
- public function get_propertyid(){
201
- return ! empty( $this->profile['w'] ) ? $this->profile['w'] : '';
202
- }
203
-
204
- public function get_network_propertyid(){
205
- return ! empty( $this->network['w'] ) ? $this->network['w'] : '';
206
- }
207
-
208
- public function get_viewid(){ // also known as profileID
209
- return ! empty( $this->profile['p'] ) ? $this->profile['p'] : '';
210
- }
211
-
212
- public function get_network_viewid(){ // also known as profileID
213
- return ! empty( $this->network['p'] ) ? $this->network['p'] : '';
214
- }
215
-
216
- public function get_key(){
217
- return ! empty( $this->profile['key'] ) ? $this->profile['key'] : '';
218
- }
219
-
220
- public function get_network_key(){
221
- return ! empty( $this->network['key'] ) ? $this->network['key'] : '';
222
- }
223
-
224
- public function get_token(){
225
- return ! empty( $this->profile['token'] ) ? $this->profile['token'] : '';
226
- }
227
-
228
- public function get_network_token(){
229
- return ! empty( $this->network['token'] ) ? $this->network['token'] : '';
230
- }
231
-
232
- public function get_referral_url(){
233
- $url = '';
234
-
235
- if ( $this->is_authed() ) {
236
- $url .= 'a' . MonsterInsights()->auth->get_accountid() . 'w' . MonsterInsights()->auth->get_propertyid() . 'p' . MonsterInsights()->auth->get_viewid() . '/';
237
- } else if ( $this->is_network_authed() ) {
238
- $url .= 'a' . MonsterInsights()->auth->get_network_accountid() . 'w' . MonsterInsights()->auth->get_network_propertyid() . 'p' . MonsterInsights()->auth->get_network_viewid() . '/';
239
- }
240
-
241
- return $url;
242
- }
243
- }
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Auth class.
4
+ *
5
+ * Helper for auth.
6
+ *
7
+ * @since 7.0.0
8
+ *
9
+ * @package MonsterInsights
10
+ * @subpackage Auth
11
+ * @author Chris Christoff
12
+ */
13
+
14
+ // Exit if accessed directly
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit;
17
+ }
18
+
19
+ final class MonsterInsights_Auth {
20
+
21
+ private $profile = array();
22
+ private $network = array();
23
+
24
+ /**
25
+ * Primary class constructor.
26
+ *
27
+ * @access public
28
+ * @since 7.0.0
29
+ */
30
+ public function __construct() {
31
+ $this->profile = $this->get_analytics_profile();
32
+ $this->network = $this->get_network_analytics_profile();
33
+ }
34
+
35
+ public function is_manual() {
36
+ return ! empty( $this->profile['manual'] );
37
+ }
38
+ public function is_network_manual() {
39
+ return ! empty( $this->network['manual'] );
40
+ }
41
+
42
+ public function is_authed() {
43
+ return ! empty( $this->profile['key'] );
44
+ }
45
+
46
+ public function is_network_authed() {
47
+ return ! empty( $this->network['key'] );
48
+ }
49
+
50
+ public function get_analytics_profile( $force = false ) {
51
+ if ( ! empty( $this->profile ) && ! $force ) {
52
+ return $this->profile;
53
+ } else {
54
+ $profile = get_option( 'monsterinsights_site_profile', array() );
55
+ $this->profile = $profile;
56
+ return $profile;
57
+ }
58
+ }
59
+
60
+ public function get_network_analytics_profile( $force = false ) {
61
+ if ( ! empty( $this->network ) && ! $force ) {
62
+ return $this->network;
63
+ } else {
64
+ $profile = get_site_option( 'monsterinsights_network_profile', array() );
65
+ $this->network = $profile;
66
+ return $profile;
67
+ }
68
+ }
69
+
70
+ public function set_analytics_profile( $data = array() ){
71
+ update_option( 'monsterinsights_site_profile', $data );
72
+ $this->profile = $data;
73
+
74
+ // If this is the first time, save the date when they connected.
75
+ $over_time = get_option( 'monsterinsights_over_time', array() );
76
+ if ( empty( $over_time['connected_date'] ) ) {
77
+ $over_time['connected_date'] = time();
78
+ update_option( 'monsterinsights_over_time', $over_time );
79
+ }
80
+ }
81
+
82
+ public function set_network_analytics_profile( $data = array() ){
83
+ update_site_option( 'monsterinsights_network_profile', $data );
84
+ $this->network = $data;
85
+ }
86
+
87
+ public function delete_analytics_profile( $migrate = true ){
88
+ if ( $migrate ) {
89
+ $newdata = array();
90
+ if ( isset( $this->profile['ua'] ) ) {
91
+ $newdata['manual'] = $this->profile['ua'];
92
+ }
93
+ $this->profile = $newdata;
94
+ $this->set_analytics_profile( $newdata );
95
+ } else {
96
+ $this->profile = array();
97
+ delete_option( 'monsterinsights_site_profile' );
98
+ }
99
+ }
100
+
101
+ public function delete_network_analytics_profile( $migrate = true ){
102
+ if ( $migrate ) {
103
+ $newdata = array();
104
+ if ( isset( $this->network['ua'] ) ) {
105
+ $newdata['manual'] = $this->network['ua'];
106
+ }
107
+ $this->network = $newdata;
108
+ $this->set_network_analytics_profile( $newdata );
109
+ } else {
110
+ $this->network = array();
111
+ delete_site_option( 'monsterinsights_network_profile' );
112
+ }
113
+ }
114
+
115
+ public function set_manual_ua( $ua = '' ) {
116
+ if ( empty( $ua ) ) {
117
+ return;
118
+ }
119
+
120
+ if ( $this->is_authed() ) {
121
+ MonsterInsights()->api_auth->delete_auth();
122
+ }
123
+
124
+ $data = array();
125
+ if ( empty( $this->profile ) ) {
126
+ $data['manual'] = $ua;
127
+ } else {
128
+ $data = $this->profile;
129
+ $data['manual'] = $ua;
130
+ }
131
+
132
+ do_action( 'monsterinsights_reports_delete_aggregate_data' );
133
+
134
+ $this->profile = $data;
135
+ $this->set_analytics_profile( $data );
136
+ }
137
+
138
+ public function set_network_manual_ua( $ua = '' ) {
139
+ if ( empty( $ua ) ) {
140
+ return;
141
+ }
142
+
143
+ if ( $this->is_network_authed() ) {
144
+ MonsterInsights()->api_auth->delete_auth();
145
+ }
146
+
147
+ $data = array();
148
+ if ( empty( $this->network ) ) {
149
+ $data['manual'] = $ua;
150
+ } else {
151
+ $data = $this->network;
152
+ $data['manual'] = $ua;
153
+ }
154
+
155
+ do_action( 'monsterinsights_reports_delete_network_aggregate_data' );
156
+
157
+ $this->network = $data;
158
+ $this->set_network_analytics_profile( $data );
159
+ }
160
+
161
+ public function delete_manual_ua() {
162
+ if ( ! empty( $this->profile ) && ! empty( $this->profile['manual'] ) ) {
163
+ unset( $this->profile['manual'] );
164
+ $this->set_analytics_profile( $this->profile );
165
+ }
166
+ }
167
+
168
+ public function delete_network_manual_ua() {
169
+ if ( ! empty( $this->network ) && ! empty( $this->network['manual'] ) ) {
170
+ unset( $this->network['manual'] );
171
+ $this->set_network_analytics_profile( $this->network );
172
+ }
173
+ }
174
+
175
+ public function get_manual_ua() {
176
+ return ! empty( $this->profile['manual'] ) ? monsterinsights_is_valid_ua( $this->profile['manual'] ) : '';
177
+ }
178
+
179
+ public function get_network_manual_ua() {
180
+ return ! empty( $this->network['manual'] ) ? monsterinsights_is_valid_ua( $this->network['manual'] ) : '';
181
+ }
182
+
183
+ public function get_ua() {
184
+ return ! empty( $this->profile['ua'] ) ? monsterinsights_is_valid_ua( $this->profile['ua'] ) : '';
185
+ }
186
+
187
+ public function get_network_ua() {
188
+ return ! empty( $this->network['ua'] ) ? monsterinsights_is_valid_ua( $this->network['ua'] ) : '';
189
+ }
190
+
191
+ public function get_viewname(){
192
+ return ! empty( $this->profile['viewname'] ) ? $this->profile['viewname'] : '';
193
+ }
194
+
195
+ public function get_network_viewname(){
196
+ return ! empty( $this->network['viewname'] ) ? $this->network['viewname'] : '';
197
+ }
198
+
199
+ public function get_accountid(){
200
+ return ! empty( $this->profile['a'] ) ? $this->profile['a'] : '';
201
+ }
202
+
203
+ public function get_network_accountid(){
204
+ return ! empty( $this->network['a'] ) ? $this->network['a'] : '';
205
+ }
206
+
207
+ public function get_propertyid(){
208
+ return ! empty( $this->profile['w'] ) ? $this->profile['w'] : '';
209
+ }
210
+
211
+ public function get_network_propertyid(){
212
+ return ! empty( $this->network['w'] ) ? $this->network['w'] : '';
213
+ }
214
+
215
+ public function get_viewid(){ // also known as profileID
216
+ return ! empty( $this->profile['p'] ) ? $this->profile['p'] : '';
217
+ }
218
+
219
+ public function get_network_viewid(){ // also known as profileID
220
+ return ! empty( $this->network['p'] ) ? $this->network['p'] : '';
221
+ }
222
+
223
+ public function get_key(){
224
+ return ! empty( $this->profile['key'] ) ? $this->profile['key'] : '';
225
+ }
226
+
227
+ public function get_network_key(){
228
+ return ! empty( $this->network['key'] ) ? $this->network['key'] : '';
229
+ }
230
+
231
+ public function get_token(){
232
+ return ! empty( $this->profile['token'] ) ? $this->profile['token'] : '';
233
+ }
234
+
235
+ public function get_network_token(){
236
+ return ! empty( $this->network['token'] ) ? $this->network['token'] : '';
237
+ }
238
+
239
+ public function get_referral_url(){
240
+ $url = '';
241
+
242
+ if ( $this->is_authed() ) {
243
+ $url .= 'a' . MonsterInsights()->auth->get_accountid() . 'w' . MonsterInsights()->auth->get_propertyid() . 'p' . MonsterInsights()->auth->get_viewid() . '/';
244
+ } else if ( $this->is_network_authed() ) {
245
+ $url .= 'a' . MonsterInsights()->auth->get_network_accountid() . 'w' . MonsterInsights()->auth->get_network_propertyid() . 'p' . MonsterInsights()->auth->get_network_viewid() . '/';
246
+ }
247
+
248
+ return $url;
249
+ }
250
+ }
includes/deprecated.php CHANGED
@@ -1,236 +1,236 @@
1
- <?php
2
- /**
3
- * Deprecated functions.
4
- *
5
- * Contains the functions used to deprecate functions and
6
- * hooks in MonsterInsights, as well as the deprecated functions
7
- * and hooks themselves, where possible.
8
- *
9
- * @since 6.0.0
10
- *
11
- * @package MonsterInsights
12
- * @subpackage Deprecated
13
- * @author Chris Christoff
14
- */
15
-
16
- // Exit if accessed directly
17
- if ( ! defined( 'ABSPATH' ) ) {
18
- exit;
19
- }
20
-
21
- /**
22
- * Fires functions attached to a deprecated filter hook.
23
- *
24
- * When a filter hook is deprecated, the apply_filters() call is replaced with
25
- * apply_filters_deprecated(), which triggers a deprecation notice and then fires
26
- * the original filter hook. Note, this is a copy of WordPress core's _apply_filters_deprecated
27
- * function, that we've copied into MonsterInsights so that we can use it on WordPress
28
- * versions older than 6.0.0 (when it was introduced to core). If we ever bump our
29
- * minimum WP version requirements above 6.0.0, we'll remove this function.
30
- *
31
- * @since 6.0.0
32
- * @access private
33
- *
34
- * @see _apply_filters_deprecated()
35
- *
36
- * @param string $tag The name of the filter hook.
37
- * @param array $args Array of additional function arguments to be passed to apply_filters().
38
- * @param string $version The version of WordPress that deprecated the hook.
39
- * @param string $message Optional. A message regarding the change. Default null.
40
- */
41
- function _monsterinsights_apply_filters_deprecated( $tag, $args, $version, $message = null ) {
42
- if ( ! has_filter( $tag ) ) {
43
- return $args[0];
44
- }
45
-
46
- _monsterinsights_deprecated_hook( $tag, $version, $message );
47
-
48
- return apply_filters_ref_array( $tag, $args );
49
- }
50
-
51
- /**
52
- * Fires functions attached to a deprecated action hook.
53
- *
54
- * When an action hook is deprecated, the do_action() call is replaced with
55
- * do_action_deprecated(), which triggers a deprecation notice and then fires
56
- * the original hook. Note, this is a copy of WordPress core's _do_action_deprecated
57
- * function, that we've copied into MonsterInsights so that we can use it on WordPress
58
- * versions older than 6.0.0 (when it was introduced to core). If we ever bump our
59
- * minimum WP version requirements above 6.0.0, we'll remove this function.
60
- *
61
- * @since 6.0.0
62
- * @access private
63
- *
64
- * @see _do_action_deprecated()
65
- *
66
- * @param string $tag The name of the action hook.
67
- * @param array $args Array of additional function arguments to be passed to do_action().
68
- * @param string $version The version of WordPress that deprecated the hook.
69
- * @param string $message Optional. A message regarding the change.
70
- */
71
- function _monsterinsights_do_action_deprecated( $tag, $args, $version, $message = null ) {
72
- if ( ! has_action( $tag ) ) {
73
- return;
74
- }
75
-
76
- _monsterinsights_deprecated_hook( $tag, $version, $message );
77
-
78
- do_action_ref_array( $tag, $args );
79
- }
80
-
81
- /**
82
- * Marks a deprecated action or filter hook as deprecated and throws a notice.
83
- *
84
- * Use the {@see 'deprecated_hook_run'} action to get the backtrace describing where
85
- * the deprecated hook was called.
86
- *
87
- * Default behavior is to trigger a user error if `WP_DEBUG` is true.
88
- *
89
- * This function is called by the do_action_deprecated() and apply_filters_deprecated()
90
- * functions, and so generally does not need to be called directly.
91
- *
92
- * Note, this is a copy of WordPress core's _deprecated_hook
93
- * function, that we've copied into MonsterInsights so that we can use it on WordPress
94
- * versions older than 6.0.0 (when it was introduced to core). If we ever bump our
95
- * minimum WP version requirements above 6.0.0, we'll remove this function.
96
- *
97
- * @since 6.0.0
98
- * @access private
99
- *
100
- * @param string $hook The hook that was used.
101
- * @param string $version The version of WordPress that deprecated the hook.
102
- * @param string $message Optional. A message regarding the change.
103
- */
104
- function _monsterinsights_deprecated_hook( $hook, $version, $message = null ) {
105
- /**
106
- * Fires when a deprecated hook is called.
107
- *
108
- * @since 6.0.0
109
- *
110
- * @param string $hook The hook that was called.
111
- * @param string $version The version of MonsterInsights that deprecated the hook used.
112
- * @param string $message A message regarding the change.
113
- */
114
- do_action( 'deprecated_hook_run', $hook, $version, $message );
115
-
116
- /**
117
- * Filters whether to trigger deprecated hook errors.
118
- *
119
- * @since 6.0.0
120
- *
121
- * @param bool $trigger Whether to trigger deprecated hook errors. Requires
122
- * `WP_DEBUG` to be defined true.
123
- */
124
- if ( ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) || monsterinsights_is_debug_mode() ) {
125
- $message = empty( $message ) ? '' : ' ' . $message;
126
- trigger_error( sprintf( esc_html__( '%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s!', 'google-analytics-for-wordpress' ), $hook, $version, '<strong>', '</strong>' ) . esc_html ( $message ) );
127
- }
128
- }
129
-
130
- /**
131
- * Marks a function as deprecated and informs when it has been used.
132
- *
133
- * There is a hook monsterinsights_deprecated_function_run that will be called that can be used
134
- * to get the backtrace up to what file and function called the deprecated
135
- * function. Based on the one in EDD core.
136
- *
137
- * The current behavior is to trigger a user error if WP_DEBUG is true.
138
- *
139
- * This function is to be used in every function that is deprecated.
140
- *
141
- * @since 6.0.0
142
- * @access private
143
- *
144
- * @uses do_action() Calls 'monsterinsights_deprecated_function_run' and passes the function name, what to use instead,
145
- * and the version the function was deprecated in.
146
- * @uses apply_filters() Calls 'monsterinsights_deprecated_function_trigger_error' and expects boolean value of true to do
147
- * trigger or false to not trigger error.
148
- *
149
- * @param string $function The function that was called
150
- * @param string $version The version of WordPress that deprecated the function
151
- * @param array $backtrace Optional. Contains stack backtrace of deprecated function
152
- * @return void
153
- */
154
- function _monsterinsights_deprecated_function( $function, $version, $backtrace = null ) {
155
-
156
- /**
157
- * Deprecated Function Action.
158
- *
159
- * Allow plugin run an action on the use of a
160
- * deprecated function. This could be used to
161
- * feed into an error logging program or file.
162
- *
163
- * @since 6.0.0
164
- *
165
- * @param string $function The function that was called.
166
- * @param string $version The version of WordPress that deprecated the function.
167
- * @param array $backtrace Optional. Contains stack backtrace of deprecated function.
168
- */
169
- do_action( 'deprecated_function_run', $function, $version, $backtrace );
170
-
171
- /**
172
- * Filters whether to trigger an error for deprecated functions.
173
- *
174
- * @since 6.0.0
175
- *
176
- * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
177
- */
178
- if ( ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) || monsterinsights_is_debug_mode() ) {
179
- trigger_error( sprintf( esc_html__( '%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s.', 'google-analytics-for-wordpress' ), $function, $version, '<strong>', '</strong>' ) );
180
- trigger_error( print_r( $backtrace, 1 ) );// Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
181
- // Alternatively we could dump this to a file.
182
- }
183
- }
184
-
185
- /**
186
- * Marks something as deprecated.
187
- *
188
- * The current behavior is to trigger a user error if WP_DEBUG is true.
189
- *
190
- * @since 6.0.0
191
- * @access private
192
- *
193
- * @uses apply_filters() Calls 'monsterinsights_deprecated_trigger_error' and expects boolean value of true to do
194
- * trigger or false to not trigger error.
195
- *
196
- * @param string $message Deprecation message shown.
197
- * @return void
198
- */
199
- function _monsterinsights_deprecated( $message ) {
200
-
201
- /**
202
- * Deprecated Message Filter.
203
- *
204
- * Allow plugin to filter the deprecated message.
205
- *
206
- * @since 6.0.0
207
- *
208
- * @param string $message Error message.
209
- */
210
- do_action( 'monsterinsights_deprecated_run', $message );
211
-
212
- $show_errors = current_user_can( 'manage_options' );
213
-
214
- /**
215
- * Deprecated Error Trigger.
216
- *
217
- * Allow plugin to filter the output error trigger.
218
- *
219
- * @since 6.0.0
220
- *
221
- * @param bool $show_errors Whether to show errors.
222
- */
223
- $show_errors = apply_filters( 'monsterinsights_deprecated_trigger_error', $show_errors );
224
- if ( ( WP_DEBUG && $show_errors ) || monsterinsights_is_debug_mode() ) {
225
- trigger_error( esc_html( $message ) );
226
- }
227
- }
228
-
229
-
230
- /**
231
- * Start Deprecated Actions & Filters.
232
- *
233
- * These backwards compatibility fixes may be removed at any time.
234
- * Users/Developers are encouraged to update their code as soon as possible.
235
- */
236
-
1
+ <?php
2
+ /**
3
+ * Deprecated functions.
4
+ *
5
+ * Contains the functions used to deprecate functions and
6
+ * hooks in MonsterInsights, as well as the deprecated functions
7
+ * and hooks themselves, where possible.
8
+ *
9
+ * @since 6.0.0
10
+ *
11
+ * @package MonsterInsights
12
+ * @subpackage Deprecated
13
+ * @author Chris Christoff
14
+ */
15
+
16
+ // Exit if accessed directly
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Fires functions attached to a deprecated filter hook.
23
+ *
24
+ * When a filter hook is deprecated, the apply_filters() call is replaced with
25
+ * apply_filters_deprecated(), which triggers a deprecation notice and then fires
26
+ * the original filter hook. Note, this is a copy of WordPress core's _apply_filters_deprecated
27
+ * function, that we've copied into MonsterInsights so that we can use it on WordPress
28
+ * versions older than 6.0.0 (when it was introduced to core). If we ever bump our
29
+ * minimum WP version requirements above 6.0.0, we'll remove this function.
30
+ *
31
+ * @since 6.0.0
32
+ * @access private
33
+ *
34
+ * @see _apply_filters_deprecated()
35
+ *
36
+ * @param string $tag The name of the filter hook.
37
+ * @param array $args Array of additional function arguments to be passed to apply_filters().
38
+ * @param string $version The version of WordPress that deprecated the hook.
39
+ * @param string $message Optional. A message regarding the change. Default null.
40
+ */
41
+ function _monsterinsights_apply_filters_deprecated( $tag, $args, $version, $message = null ) {
42
+ if ( ! has_filter( $tag ) ) {
43
+ return $args[0];
44
+ }
45
+
46
+ _monsterinsights_deprecated_hook( $tag, $version, $message );
47
+
48
+ return apply_filters_ref_array( $tag, $args );
49
+ }
50
+
51
+ /**
52
+ * Fires functions attached to a deprecated action hook.
53
+ *
54
+ * When an action hook is deprecated, the do_action() call is replaced with
55
+ * do_action_deprecated(), which triggers a deprecation notice and then fires
56
+ * the original hook. Note, this is a copy of WordPress core's _do_action_deprecated
57
+ * function, that we've copied into MonsterInsights so that we can use it on WordPress
58
+ * versions older than 6.0.0 (when it was introduced to core). If we ever bump our
59
+ * minimum WP version requirements above 6.0.0, we'll remove this function.
60
+ *
61
+ * @since 6.0.0
62
+ * @access private
63
+ *
64
+ * @see _do_action_deprecated()
65
+ *
66
+ * @param string $tag The name of the action hook.
67
+ * @param array $args Array of additional function arguments to be passed to do_action().
68
+ * @param string $version The version of WordPress that deprecated the hook.
69
+ * @param string $message Optional. A message regarding the change.
70
+ */
71
+ function _monsterinsights_do_action_deprecated( $tag, $args, $version, $message = null ) {
72
+ if ( ! has_action( $tag ) ) {
73
+ return;
74
+ }
75
+
76
+ _monsterinsights_deprecated_hook( $tag, $version, $message );
77
+
78
+ do_action_ref_array( $tag, $args );
79
+ }
80
+
81
+ /**
82
+ * Marks a deprecated action or filter hook as deprecated and throws a notice.
83
+ *
84
+ * Use the {@see 'deprecated_hook_run'} action to get the backtrace describing where
85
+ * the deprecated hook was called.
86
+ *
87
+ * Default behavior is to trigger a user error if `WP_DEBUG` is true.
88
+ *
89
+ * This function is called by the do_action_deprecated() and apply_filters_deprecated()
90
+ * functions, and so generally does not need to be called directly.
91
+ *
92
+ * Note, this is a copy of WordPress core's _deprecated_hook
93
+ * function, that we've copied into MonsterInsights so that we can use it on WordPress
94
+ * versions older than 6.0.0 (when it was introduced to core). If we ever bump our
95
+ * minimum WP version requirements above 6.0.0, we'll remove this function.
96
+ *
97
+ * @since 6.0.0
98
+ * @access private
99
+ *
100
+ * @param string $hook The hook that was used.
101
+ * @param string $version The version of WordPress that deprecated the hook.
102
+ * @param string $message Optional. A message regarding the change.
103
+ */
104
+ function _monsterinsights_deprecated_hook( $hook, $version, $message = null ) {
105
+ /**
106
+ * Fires when a deprecated hook is called.
107
+ *
108
+ * @since 6.0.0
109
+ *
110
+ * @param string $hook The hook that was called.
111
+ * @param string $version The version of MonsterInsights that deprecated the hook used.
112
+ * @param string $message A message regarding the change.
113
+ */
114
+ do_action( 'deprecated_hook_run', $hook, $version, $message );
115
+
116
+ /**
117
+ * Filters whether to trigger deprecated hook errors.
118
+ *
119
+ * @since 6.0.0
120
+ *
121
+ * @param bool $trigger Whether to trigger deprecated hook errors. Requires
122
+ * `WP_DEBUG` to be defined true.
123
+ */
124
+ if ( ( WP_DEBUG && apply_filters( 'deprecated_hook_trigger_error', true ) ) || monsterinsights_is_debug_mode() ) {
125
+ $message = empty( $message ) ? '' : ' ' . $message;
126
+ trigger_error( sprintf( esc_html__( '%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s!', 'google-analytics-for-wordpress' ), $hook, $version, '<strong>', '</strong>' ) . esc_html ( $message ) );
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Marks a function as deprecated and informs when it has been used.
132
+ *
133
+ * There is a hook monsterinsights_deprecated_function_run that will be called that can be used
134
+ * to get the backtrace up to what file and function called the deprecated
135
+ * function. Based on the one in EDD core.
136
+ *
137
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
138
+ *
139
+ * This function is to be used in every function that is deprecated.
140
+ *
141
+ * @since 6.0.0
142
+ * @access private
143
+ *
144
+ * @uses do_action() Calls 'monsterinsights_deprecated_function_run' and passes the function name, what to use instead,
145
+ * and the version the function was deprecated in.
146
+ * @uses apply_filters() Calls 'monsterinsights_deprecated_function_trigger_error' and expects boolean value of true to do
147
+ * trigger or false to not trigger error.
148
+ *
149
+ * @param string $function The function that was called
150
+ * @param string $version The version of WordPress that deprecated the function
151
+ * @param array $backtrace Optional. Contains stack backtrace of deprecated function
152
+ * @return void
153
+ */
154
+ function _monsterinsights_deprecated_function( $function, $version, $backtrace = null ) {
155
+
156
+ /**
157
+ * Deprecated Function Action.
158
+ *
159
+ * Allow plugin run an action on the use of a
160
+ * deprecated function. This could be used to
161
+ * feed into an error logging program or file.
162
+ *
163
+ * @since 6.0.0
164
+ *
165
+ * @param string $function The function that was called.
166
+ * @param string $version The version of WordPress that deprecated the function.
167
+ * @param array $backtrace Optional. Contains stack backtrace of deprecated function.
168
+ */
169
+ do_action( 'deprecated_function_run', $function, $version, $backtrace );
170
+
171
+ /**
172
+ * Filters whether to trigger an error for deprecated functions.
173
+ *
174
+ * @since 6.0.0
175
+ *
176
+ * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
177
+ */
178
+ if ( ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) || monsterinsights_is_debug_mode() ) {
179
+ trigger_error( sprintf( esc_html__( '%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s.', 'google-analytics-for-wordpress' ), $function, $version, '<strong>', '</strong>' ) );
180
+ trigger_error( print_r( $backtrace, 1 ) );// Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
181
+ // Alternatively we could dump this to a file.
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Marks something as deprecated.
187
+ *
188
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
189
+ *
190
+ * @since 6.0.0
191
+ * @access private
192
+ *
193
+ * @uses apply_filters() Calls 'monsterinsights_deprecated_trigger_error' and expects boolean value of true to do
194
+ * trigger or false to not trigger error.
195
+ *
196
+ * @param string $message Deprecation message shown.
197
+ * @return void
198
+ */
199
+ function _monsterinsights_deprecated( $message ) {
200
+
201
+ /**
202
+ * Deprecated Message Filter.
203
+ *
204
+ * Allow plugin to filter the deprecated message.
205
+ *
206
+ * @since 6.0.0
207
+ *
208
+ * @param string $message Error message.
209
+ */
210
+ do_action( 'monsterinsights_deprecated_run', $message );
211
+
212
+ $show_errors = current_user_can( 'manage_options' );
213
+
214
+ /**
215
+ * Deprecated Error Trigger.
216
+ *
217
+ * Allow plugin to filter the output error trigger.
218
+ *
219
+ * @since 6.0.0
220
+ *
221
+ * @param bool $show_errors Whether to show errors.
222
+ */
223
+ $show_errors = apply_filters( 'monsterinsights_deprecated_trigger_error', $show_errors );
224
+ if ( ( WP_DEBUG && $show_errors ) || monsterinsights_is_debug_mode() ) {
225
+ trigger_error( esc_html( $message ) );
226
+ }
227
+ }
228
+
229
+
230
+ /**
231
+ * Start Deprecated Actions & Filters.
232
+ *
233
+ * These backwards compatibility fixes may be removed at any time.
234
+ * Users/Developers are encouraged to update their code as soon as possible.
235
+ */
236
+
includes/frontend/class-tracking-abstract.php CHANGED
@@ -1,79 +1,79 @@
1
- <?php
2
- /**
3
- * Tracking abstract class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
- class MonsterInsights_Tracking_Abstract {
17
-
18
- /**
19
- * Holds the name of the tracking type.
20
- *
21
- * @since 6.0.0
22
- * @access public
23
- *
24
- * @var string $name Name of the tracking type.
25
- */
26
- public $name = 'abstract';
27
-
28
- /**
29
- * Version of the tracking class.
30
- *
31
- * @since 6.0.0
32
- * @access public
33
- *
34
- * @var string $version Version of the tracking class.
35
- */
36
- public $version = '1.0.0';
37
-
38
- /**
39
- * Primary class constructor.
40
- *
41
- * @since 6.0.0
42
- * @access public
43
- */
44
- public function __construct() {
45
-
46
- }
47
-
48
- /**
49
- * Get frontend tracking options.
50
- *
51
- * This function is used to return an array of parameters
52
- * for the frontend_output() function to output. These are
53
- * generally dimensions and turned on GA features.
54
- *
55
- * @since 6.0.0
56
- * @access public
57
- *
58
- * @return array Array of the options to use.
59
- */
60
- public function frontend_tracking_options( ) {
61
- return array();
62
- }
63
-
64
- /**
65
- * Get frontend output.
66
- *
67
- * This function is used to return the Javascript
68
- * to output in the head of the page for the given
69
- * tracking method.
70
- *
71
- * @since 6.0.0
72
- * @access public
73
- *
74
- * @return string Javascript to output.
75
- */
76
- public function frontend_output( ) {
77
- return "<!-- MonsterInsights Abstract Tracking class -->";
78
- }
79
  }
1
+ <?php
2
+ /**
3
+ * Tracking abstract class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ class MonsterInsights_Tracking_Abstract {
17
+
18
+ /**
19
+ * Holds the name of the tracking type.
20
+ *
21
+ * @since 6.0.0
22
+ * @access public
23
+ *
24
+ * @var string $name Name of the tracking type.
25
+ */
26
+ public $name = 'abstract';
27
+
28
+ /**
29
+ * Version of the tracking class.
30
+ *
31
+ * @since 6.0.0
32
+ * @access public
33
+ *
34
+ * @var string $version Version of the tracking class.
35
+ */
36
+ public $version = '1.0.0';
37
+
38
+ /**
39
+ * Primary class constructor.
40
+ *
41
+ * @since 6.0.0
42
+ * @access public
43
+ */
44
+ public function __construct() {
45
+
46
+ }
47
+
48
+ /**
49
+ * Get frontend tracking options.
50
+ *
51
+ * This function is used to return an array of parameters
52
+ * for the frontend_output() function to output. These are
53
+ * generally dimensions and turned on GA features.
54
+ *
55
+ * @since 6.0.0
56
+ * @access public
57
+ *
58
+ * @return array Array of the options to use.
59
+ */
60
+ public function frontend_tracking_options( ) {
61
+ return array();
62
+ }
63
+
64
+ /**
65
+ * Get frontend output.
66
+ *
67
+ * This function is used to return the Javascript
68
+ * to output in the head of the page for the given
69
+ * tracking method.
70
+ *
71
+ * @since 6.0.0
72
+ * @access public
73
+ *
74
+ * @return string Javascript to output.
75
+ */
76
+ public function frontend_output( ) {
77
+ return "<!-- MonsterInsights Abstract Tracking class -->";
78
+ }
79
  }
includes/frontend/events/class-analytics-events.php CHANGED
@@ -1,116 +1,116 @@
1
- <?php
2
- /**
3
- * Events JS class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Events
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- class MonsterInsights_Analytics_Events {
18
-
19
- /**
20
- * Holds the name of the events type.
21
- *
22
- * @since 6.0.0
23
- * @access public
24
- *
25
- * @var string $name Name of the events type.
26
- */
27
- public $name = 'js';
28
-
29
- /**
30
- * Version of the events class.
31
- *
32
- * @since 6.0.0
33
- * @access public
34
- *
35
- * @var string $version Version of the events class.
36
- */
37
- public $version = '1.0.0';
38
-
39
- /**
40
- * Primary class constructor.
41
- *
42
- * @since 6.0.0
43
- * @access public
44
- */
45
- public function __construct() {
46
- add_action( 'wp_enqueue_scripts', array( $this, 'output_javascript' ), 9 );
47
- //add_action( 'login_head', array( $this, 'output_javascript' ), 9 );
48
- }
49
-
50
- /**
51
- * Outputs the Javascript for JS tracking on the page.
52
- *
53
- * @since 6.0.0
54
- * @access public
55
- *
56
- * @return string
57
- */
58
- public function output_javascript() {
59
- // Affiliate Links
60
- $inbound_paths = monsterinsights_get_option( 'affiliate_links', array() );
61
- if ( ! is_array( $inbound_paths ) ) {
62
- $inbound_paths = array();
63
- } else {
64
- foreach( $inbound_paths as $index => $pair ) {
65
- // if empty pair, unset and continue
66
- if ( empty( $pair['path'] ) ) {
67
- unset( $inbound_paths[$index] );
68
- continue;
69
- }
70
-
71
- // if path does not start with a /, start it with that
72
- $path = ! empty( $pair['path'] ) ? $pair['path'] : 'aff';
73
- $inbound_paths[$index]['path'] = trim( $path );
74
-
75
- // js escape the link label
76
- $label = ! empty( $pair['label'] ) ? $pair['label'] : 'aff';
77
- $inbound_paths[$index]['label'] = esc_js( trim( $label ) );
78
- }
79
- }
80
-
81
- $inbound_paths = wp_json_encode( $inbound_paths );
82
-
83
- // Get download extensions to track
84
- $download_extensions = monsterinsights_get_option( 'extensions_of_files', '' );
85
- $download_extensions = explode( ',', str_replace( '.', '', $download_extensions ) );
86
- if ( ! is_array( $download_extensions ) ) {
87
- $download_extensions = array( $download_extensions );
88
- }
89
- $i = 0;
90
- foreach( $download_extensions as $extension ){
91
- $download_extensions[ $i ] = esc_js( trim( $extension ) );
92
- $i++;
93
- }
94
-
95
- $download_extensions = implode( ",", $download_extensions );
96
-
97
- $hash_tracking = monsterinsights_get_option( 'hash_tracking', false ) ? 'true' : 'false';
98
-
99
- $suffix = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
100
- if ( ! file_exists( MONSTERINSIGHTS_PLUGIN_DIR . 'assets/js/frontend.min.js' ) ) {
101
- $suffix = '';
102
- }
103
- wp_enqueue_script( 'monsterinsights-frontend-script', plugins_url( 'assets/js/frontend' . $suffix . '.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), false );
104
- wp_localize_script(
105
- 'monsterinsights-frontend-script',
106
- 'monsterinsights_frontend',
107
- array(
108
- 'js_events_tracking' => 'true',
109
- 'download_extensions' => $download_extensions, /* Let's get the extensions to track */
110
- 'inbound_paths' => $inbound_paths, /* Let's get the internal paths to track */
111
- 'home_url' => home_url(), /* Let's get the url to compare for external/internal use */
112
- 'hash_tracking' => $hash_tracking, /* Should hash track */
113
- )
114
- );
115
- }
116
  }
1
+ <?php
2
+ /**
3
+ * Events JS class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Events
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ class MonsterInsights_Analytics_Events {
18
+
19
+ /**
20
+ * Holds the name of the events type.
21
+ *
22
+ * @since 6.0.0
23
+ * @access public
24
+ *
25
+ * @var string $name Name of the events type.
26
+ */
27
+ public $name = 'js';
28
+
29
+ /**
30
+ * Version of the events class.
31
+ *
32
+ * @since 6.0.0
33
+ * @access public
34
+ *
35
+ * @var string $version Version of the events class.
36
+ */
37
+ public $version = '1.0.0';
38
+
39
+ /**
40
+ * Primary class constructor.
41
+ *
42
+ * @since 6.0.0
43
+ * @access public
44
+ */
45
+ public function __construct() {
46
+ add_action( 'wp_enqueue_scripts', array( $this, 'output_javascript' ), 9 );
47
+ //add_action( 'login_head', array( $this, 'output_javascript' ), 9 );
48
+ }
49
+
50
+ /**
51
+ * Outputs the Javascript for JS tracking on the page.
52
+ *
53
+ * @since 6.0.0
54
+ * @access public
55
+ *
56
+ * @return string
57
+ */
58
+ public function output_javascript() {
59
+ // Affiliate Links
60
+ $inbound_paths = monsterinsights_get_option( 'affiliate_links', array() );
61
+ if ( ! is_array( $inbound_paths ) ) {
62
+ $inbound_paths = array();
63
+ } else {
64
+ foreach( $inbound_paths as $index => $pair ) {
65
+ // if empty pair, unset and continue
66
+ if ( empty( $pair['path'] ) ) {
67
+ unset( $inbound_paths[$index] );
68
+ continue;
69
+ }
70
+
71
+ // if path does not start with a /, start it with that
72
+ $path = ! empty( $pair['path'] ) ? $pair['path'] : 'aff';
73
+ $inbound_paths[$index]['path'] = trim( $path );
74
+
75
+ // js escape the link label
76
+ $label = ! empty( $pair['label'] ) ? $pair['label'] : 'aff';
77
+ $inbound_paths[$index]['label'] = esc_js( trim( $label ) );
78
+ }
79
+ }
80
+
81
+ $inbound_paths = wp_json_encode( $inbound_paths );
82
+
83
+ // Get download extensions to track
84
+ $download_extensions = monsterinsights_get_option( 'extensions_of_files', '' );
85
+ $download_extensions = explode( ',', str_replace( '.', '', $download_extensions ) );
86
+ if ( ! is_array( $download_extensions ) ) {
87
+ $download_extensions = array( $download_extensions );
88
+ }
89
+ $i = 0;
90
+ foreach( $download_extensions as $extension ){
91
+ $download_extensions[ $i ] = esc_js( trim( $extension ) );
92
+ $i++;
93
+ }
94
+
95
+ $download_extensions = implode( ",", $download_extensions );
96
+
97
+ $hash_tracking = monsterinsights_get_option( 'hash_tracking', false ) ? 'true' : 'false';
98
+
99
+ $suffix = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
100
+ if ( ! file_exists( MONSTERINSIGHTS_PLUGIN_DIR . 'assets/js/frontend.min.js' ) ) {
101
+ $suffix = '';
102
+ }
103
+ wp_enqueue_script( 'monsterinsights-frontend-script', plugins_url( 'assets/js/frontend' . $suffix . '.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), false );
104
+ wp_localize_script(
105
+ 'monsterinsights-frontend-script',
106
+ 'monsterinsights_frontend',
107
+ array(
108
+ 'js_events_tracking' => 'true',
109
+ 'download_extensions' => $download_extensions, /* Let's get the extensions to track */
110
+ 'inbound_paths' => $inbound_paths, /* Let's get the internal paths to track */
111
+ 'home_url' => home_url(), /* Let's get the url to compare for external/internal use */
112
+ 'hash_tracking' => $hash_tracking, /* Should hash track */
113
+ )
114
+ );
115
+ }
116
  }
includes/frontend/events/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
includes/frontend/frontend.php CHANGED
@@ -1,185 +1,193 @@
1
- <?php
2
- /**
3
- * Frontend events tracking.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
-
17
- /**
18
- * Get frontend tracking options.
19
- *
20
- * This function is used to return an array of parameters
21
- * for the frontend_output() function to output. These are
22
- * generally dimensions and turned on GA features.
23
- *
24
- * @since 7.0.0
25
- * @access public
26
- *
27
- * @return array Array of the options to use.
28
- */
29
- function monsterinsights_tracking_script( ) {
30
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/class-tracking-abstract.php';
31
-
32
- $mode = is_preview() ? 'preview' : 'analytics';
33
-
34
- do_action( 'monsterinsights_tracking_before_' . $mode );
35
- do_action( 'monsterinsights_tracking_before', $mode );
36
- if ( $mode === 'preview' ) {
37
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/tracking/class-tracking-preview.php';
38
- $tracking = new MonsterInsights_Tracking_Preview();
39
- echo $tracking->frontend_output();
40
- } else {
41
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/tracking/class-tracking-analytics.php';
42
- $tracking = new MonsterInsights_Tracking_Analytics();
43
- echo $tracking->frontend_output();
44
- }
45
-
46
- do_action( 'monsterinsights_tracking_after_' . $mode );
47
- do_action( 'monsterinsights_tracking_after', $mode );
48
- }
49
- add_action( 'wp_head', 'monsterinsights_tracking_script', 6 );
50
- //add_action( 'login_head', 'monsterinsights_tracking_script', 6 );
51
-
52
- /**
53
- * Get frontend tracking options.
54
- *
55
- * This function is used to return an array of parameters
56
- * for the frontend_output() function to output. These are
57
- * generally dimensions and turned on GA features.
58
- *
59
- * @since 6.0.0
60
- * @access public
61
- *
62
- * @return array Array of the options to use.
63
- */
64
- function monsterinsights_events_tracking( ) {
65
- $track_user = monsterinsights_track_user();
66
-
67
- if ( $track_user ) {
68
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/events/class-analytics-events.php';
69
- new MonsterInsights_Analytics_Events();
70
- } else {
71
- // User is in the disabled group or events mode is off
72
- }
73
- }
74
- add_action( 'template_redirect', 'monsterinsights_events_tracking', 9 );
75
-
76
- /**
77
- * Add the UTM source parameters in the RSS feeds to track traffic.
78
- *
79
- * @since 6.0.0
80
- * @access public
81
- *
82
- * @param string $guid The link for the RSS feed.
83
- *
84
- * @return string The new link for the RSS feed.
85
- */
86
- function monsterinsights_rss_link_tagger( $guid ) {
87
- global $post;
88
-
89
- if ( monsterinsights_get_option( 'tag_links_in_rss', false ) ){
90
- if ( is_feed() ) {
91
- if ( monsterinsights_get_option( 'allow_anchor', false ) ) {
92
- $delimiter = '#';
93
- } else {
94
- $delimiter = '?';
95
- if ( strpos( $guid, $delimiter ) > 0 ) {
96
- $delimiter = '&amp;';
97
- }
98
- }
99
- return $guid . $delimiter . 'utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=' . urlencode( $post->post_name );
100
- }
101
- }
102
- return $guid;
103
- }
104
- add_filter( 'the_permalink_rss', 'monsterinsights_rss_link_tagger', 99 );
105
-
106
- /**
107
- * Add an admin bar menu item on the frontend.
108
- *
109
- * @since 7.5.0
110
- *
111
- * @return void
112
- */
113
- function monsterinsights_add_admin_bar_menu() {
114
- if ( monsterinsights_get_option( 'hide_admin_bar_reports' ) || function_exists( 'monsterinsights_is_reports_page' ) && monsterinsights_is_reports_page() ) {
115
- return;
116
- }
117
-
118
- global $wp_admin_bar;
119
-
120
- $args = array(
121
- 'id' => 'monsterinsights_frontend_button',
122
- 'title' => '<span class="ab-icon dashicons-before dashicons-chart-bar"></span> Insights', // Maybe allow translation?
123
- 'href' => '#',
124
- );
125
-
126
- if ( method_exists( $wp_admin_bar, 'add_menu' ) ) {
127
- $wp_admin_bar->add_menu( $args );
128
- }
129
- }
130
-
131
- add_action( 'admin_bar_menu', 'monsterinsights_add_admin_bar_menu', 999 );
132
-
133
- /**
134
- * Load the scripts needed for the admin bar.
135
- *
136
- * @since 7.5.0
137
- *
138
- * @return void
139
- */
140
- function monsterinsights_frontend_admin_bar_scripts() {
141
- if ( ! is_admin_bar_showing() || monsterinsights_get_option( 'hide_admin_bar_reports' ) || function_exists( 'monsterinsights_is_reports_page' ) && monsterinsights_is_reports_page() ) {
142
- return;
143
- }
144
-
145
- $version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
146
- $rtl = is_rtl() ? '.rtl' : '';
147
- $frontend_js_url = defined( 'MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL' ) && MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL ? MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL : plugins_url( $version_path . '/assets/vue/js/frontend.js', MONSTERINSIGHTS_PLUGIN_FILE );
148
-
149
- if ( ! defined( 'MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL' ) ) {
150
- wp_enqueue_style( 'monsterinsights-vue-frontend-style', plugins_url( $version_path . '/assets/vue/css/frontend' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
151
- wp_enqueue_script( 'monsterinsights-vue-vendors', plugins_url( $version_path . '/assets/vue/js/chunk-vendors.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
152
- wp_enqueue_script( 'monsterinsights-vue-common', plugins_url( $version_path . '/assets/vue/js/chunk-common.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
153
- }
154
-
155
- wp_register_script( 'monsterinsights-vue-frontend', $frontend_js_url, array(), monsterinsights_get_asset_version(), true );
156
- wp_enqueue_script( 'monsterinsights-vue-frontend' );
157
-
158
- $page_title = is_singular() ? get_the_title() : monsterinsights_get_page_title();
159
-
160
- // Check if any of the other admin scripts are enqueued, if so, use their object.
161
- if ( ! wp_script_is( 'monsterinsights-vue-script' ) && ! wp_script_is( 'monsterinsights-vue-reports' ) && ! wp_script_is( 'monsterinsights-vue-widget' ) ) {
162
- wp_localize_script(
163
- 'monsterinsights-vue-frontend',
164
- 'monsterinsights',
165
- array(
166
- 'ajax' => admin_url( 'admin-ajax.php' ),
167
- 'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
168
- 'network' => is_network_admin(),
169
- 'translations' => wp_get_jed_locale_data( monsterinsights_is_pro_version() ? 'ga-premium' : 'google-analytics-for-wordpress' ),
170
- 'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
171
- 'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
172
- 'page_id' => is_singular() ? get_the_ID() : false,
173
- 'page_title' => $page_title,
174
- 'plugin_version' => MONSTERINSIGHTS_VERSION,
175
- 'shareasale_id' => monsterinsights_get_shareasale_id(),
176
- 'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
177
- 'is_admin' => is_admin(),
178
- 'reports_url' => add_query_arg( 'page', 'monsterinsights_reports', admin_url( 'admin.php' ) ),
179
- )
180
- );
181
- }
182
- }
183
-
184
- add_action( 'wp_enqueue_scripts', 'monsterinsights_frontend_admin_bar_scripts' );
185
- add_action( 'admin_enqueue_scripts', 'monsterinsights_frontend_admin_bar_scripts', 1005 );
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Frontend events tracking.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+
17
+ /**
18
+ * Get frontend tracking options.
19
+ *
20
+ * This function is used to return an array of parameters
21
+ * for the frontend_output() function to output. These are
22
+ * generally dimensions and turned on GA features.
23
+ *
24
+ * @since 7.0.0
25
+ * @access public
26
+ *
27
+ * @return array Array of the options to use.
28
+ */
29
+ function monsterinsights_tracking_script( ) {
30
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/class-tracking-abstract.php';
31
+
32
+ $mode = is_preview() ? 'preview' : 'analytics';
33
+
34
+ do_action( 'monsterinsights_tracking_before_' . $mode );
35
+ do_action( 'monsterinsights_tracking_before', $mode );
36
+ if ( $mode === 'preview' ) {
37
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/tracking/class-tracking-preview.php';
38
+ $tracking = new MonsterInsights_Tracking_Preview();
39
+ echo $tracking->frontend_output();
40
+ } else {
41
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/tracking/class-tracking-analytics.php';
42
+ $tracking = new MonsterInsights_Tracking_Analytics();
43
+ echo $tracking->frontend_output();
44
+ }
45
+
46
+ do_action( 'monsterinsights_tracking_after_' . $mode );
47
+ do_action( 'monsterinsights_tracking_after', $mode );
48
+ }
49
+ add_action( 'wp_head', 'monsterinsights_tracking_script', 6 );
50
+ //add_action( 'login_head', 'monsterinsights_tracking_script', 6 );
51
+
52
+ /**
53
+ * Get frontend tracking options.
54
+ *
55
+ * This function is used to return an array of parameters
56
+ * for the frontend_output() function to output. These are
57
+ * generally dimensions and turned on GA features.
58
+ *
59
+ * @since 6.0.0
60
+ * @access public
61
+ *
62
+ * @return array Array of the options to use.
63
+ */
64
+ function monsterinsights_events_tracking( ) {
65
+ $track_user = monsterinsights_track_user();
66
+
67
+ if ( $track_user ) {
68
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/events/class-analytics-events.php';
69
+ new MonsterInsights_Analytics_Events();
70
+ } else {
71
+ // User is in the disabled group or events mode is off
72
+ }
73
+ }
74
+ add_action( 'template_redirect', 'monsterinsights_events_tracking', 9 );
75
+
76
+ /**
77
+ * Add the UTM source parameters in the RSS feeds to track traffic.
78
+ *
79
+ * @since 6.0.0
80
+ * @access public
81
+ *
82
+ * @param string $guid The link for the RSS feed.
83
+ *
84
+ * @return string The new link for the RSS feed.
85
+ */
86
+ function monsterinsights_rss_link_tagger( $guid ) {
87
+ global $post;
88
+
89
+ if ( monsterinsights_get_option( 'tag_links_in_rss', false ) ){
90
+ if ( is_feed() ) {
91
+ if ( monsterinsights_get_option( 'allow_anchor', false ) ) {
92
+ $delimiter = '#';
93
+ } else {
94
+ $delimiter = '?';
95
+ if ( strpos( $guid, $delimiter ) > 0 ) {
96
+ $delimiter = '&amp;';
97
+ }
98
+ }
99
+ return $guid . $delimiter . 'utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=' . urlencode( $post->post_name );
100
+ }
101
+ }
102
+ return $guid;
103
+ }
104
+ add_filter( 'the_permalink_rss', 'monsterinsights_rss_link_tagger', 99 );
105
+
106
+
107
+ /**
108
+ * Checks used for loading the frontend scripts/admin bar button.
109
+ */
110
+ function monsterinsights_prevent_loading_frontend_reports() {
111
+ return ! current_user_can( 'monsterinsights_view_dashboard' ) || monsterinsights_get_option( 'hide_admin_bar_reports' ) || function_exists( 'monsterinsights_is_reports_page' ) && monsterinsights_is_reports_page();
112
+ }
113
+
114
+ /**
115
+ * Add an admin bar menu item on the frontend.
116
+ *
117
+ * @since 7.5.0
118
+ *
119
+ * @return void
120
+ */
121
+ function monsterinsights_add_admin_bar_menu() {
122
+ if ( monsterinsights_prevent_loading_frontend_reports() ) {
123
+ return;
124
+ }
125
+
126
+ global $wp_admin_bar;
127
+
128
+ $args = array(
129
+ 'id' => 'monsterinsights_frontend_button',
130
+ 'title' => '<span class="ab-icon dashicons-before dashicons-chart-bar"></span> Insights', // Maybe allow translation?
131
+ 'href' => '#',
132
+ );
133
+
134
+ if ( method_exists( $wp_admin_bar, 'add_menu' ) ) {
135
+ $wp_admin_bar->add_menu( $args );
136
+ }
137
+ }
138
+
139
+ add_action( 'admin_bar_menu', 'monsterinsights_add_admin_bar_menu', 999 );
140
+
141
+ /**
142
+ * Load the scripts needed for the admin bar.
143
+ *
144
+ * @since 7.5.0
145
+ *
146
+ * @return void
147
+ */
148
+ function monsterinsights_frontend_admin_bar_scripts() {
149
+ if ( monsterinsights_prevent_loading_frontend_reports() ) {
150
+ return;
151
+ }
152
+
153
+ $version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
154
+ $rtl = is_rtl() ? '.rtl' : '';
155
+ $frontend_js_url = defined( 'MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL' ) && MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL ? MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL : plugins_url( $version_path . '/assets/vue/js/frontend.js', MONSTERINSIGHTS_PLUGIN_FILE );
156
+
157
+ if ( ! defined( 'MONSTERINSIGHTS_LOCAL_FRONTEND_JS_URL' ) ) {
158
+ wp_enqueue_style( 'monsterinsights-vue-frontend-style', plugins_url( $version_path . '/assets/vue/css/frontend' . $rtl . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
159
+ wp_enqueue_script( 'monsterinsights-vue-vendors', plugins_url( $version_path . '/assets/vue/js/chunk-vendors.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
160
+ wp_enqueue_script( 'monsterinsights-vue-common', plugins_url( $version_path . '/assets/vue/js/chunk-common.js', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version(), true );
161
+ }
162
+
163
+ wp_register_script( 'monsterinsights-vue-frontend', $frontend_js_url, array(), monsterinsights_get_asset_version(), true );
164
+ wp_enqueue_script( 'monsterinsights-vue-frontend' );
165
+
166
+ $page_title = is_singular() ? get_the_title() : monsterinsights_get_page_title();
167
+
168
+ // Check if any of the other admin scripts are enqueued, if so, use their object.
169
+ if ( ! wp_script_is( 'monsterinsights-vue-script' ) && ! wp_script_is( 'monsterinsights-vue-reports' ) && ! wp_script_is( 'monsterinsights-vue-widget' ) ) {
170
+ wp_localize_script(
171
+ 'monsterinsights-vue-frontend',
172
+ 'monsterinsights',
173
+ array(
174
+ 'ajax' => admin_url( 'admin-ajax.php' ),
175
+ 'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
176
+ 'network' => is_network_admin(),
177
+ 'translations' => wp_get_jed_locale_data( monsterinsights_is_pro_version() ? 'ga-premium' : 'google-analytics-for-wordpress' ),
178
+ 'assets' => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
179
+ 'addons_url' => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
180
+ 'page_id' => is_singular() ? get_the_ID() : false,
181
+ 'page_title' => $page_title,
182
+ 'plugin_version' => MONSTERINSIGHTS_VERSION,
183
+ 'shareasale_id' => monsterinsights_get_shareasale_id(),
184
+ 'shareasale_url' => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
185
+ 'is_admin' => is_admin(),
186
+ 'reports_url' => add_query_arg( 'page', 'monsterinsights_reports', admin_url( 'admin.php' ) ),
187
+ )
188
+ );
189
+ }
190
+ }
191
+
192
+ add_action( 'wp_enqueue_scripts', 'monsterinsights_frontend_admin_bar_scripts' );
193
+ add_action( 'admin_enqueue_scripts', 'monsterinsights_frontend_admin_bar_scripts', 1005 );
includes/frontend/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
includes/frontend/seedprod.php CHANGED
@@ -1,45 +1,45 @@
1
- <?php
2
- /**
3
- * SeedProd Tracking for 404 and Coming Soon.
4
- *
5
- * @since 7.3.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
- // 1. Disable SeedProd settings (done in seedprod)
17
- // 2. Output tracking code, if settings is not set to use wp_head() (done in seedprod and below)
18
- // 3. Disable ga_tracking in their setting (done in seedprod)
19
- function monsterinsights_seedprod_tracking( $settings ) {
20
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/class-tracking-abstract.php';
21
-
22
-
23
- do_action( 'monsterinsights_tracking_before_analytics' );
24
- do_action( 'monsterinsights_tracking_before', 'analytics' );
25
-
26
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/tracking/class-tracking-analytics.php';
27
- $tracking = new MonsterInsights_Tracking_Analytics();
28
- echo $tracking->frontend_output();
29
-
30
- do_action( 'monsterinsights_tracking_after_analytics' );
31
- do_action( 'monsterinsights_tracking_after', 'analytics' );
32
-
33
- $track_user = monsterinsights_track_user();
34
-
35
- if ( $track_user ) {
36
- require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/events/class-analytics-events.php';
37
- new MonsterInsights_Analytics_Events();
38
-
39
- // Let's run form tracking if we find it
40
- if ( function_exists( 'monsterinsights_forms_output_after_script' ) ) {
41
- monsterinsights_forms_output_after_script( array() );
42
- }
43
- }
44
- }
45
  add_action( 'seedprod_monsterinsights_output_tracking', 'monsterinsights_seedprod_tracking', 6, 1 );
1
+ <?php
2
+ /**
3
+ * SeedProd Tracking for 404 and Coming Soon.
4
+ *
5
+ * @since 7.3.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ // 1. Disable SeedProd settings (done in seedprod)
17
+ // 2. Output tracking code, if settings is not set to use wp_head() (done in seedprod and below)
18
+ // 3. Disable ga_tracking in their setting (done in seedprod)
19
+ function monsterinsights_seedprod_tracking( $settings ) {
20
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/class-tracking-abstract.php';
21
+
22
+
23
+ do_action( 'monsterinsights_tracking_before_analytics' );
24
+ do_action( 'monsterinsights_tracking_before', 'analytics' );
25
+
26
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/tracking/class-tracking-analytics.php';
27
+ $tracking = new MonsterInsights_Tracking_Analytics();
28
+ echo $tracking->frontend_output();
29
+
30
+ do_action( 'monsterinsights_tracking_after_analytics' );
31
+ do_action( 'monsterinsights_tracking_after', 'analytics' );
32
+
33
+ $track_user = monsterinsights_track_user();
34
+
35
+ if ( $track_user ) {
36
+ require_once plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE ) . 'includes/frontend/events/class-analytics-events.php';
37
+ new MonsterInsights_Analytics_Events();
38
+
39
+ // Let's run form tracking if we find it
40
+ if ( function_exists( 'monsterinsights_forms_output_after_script' ) ) {
41
+ monsterinsights_forms_output_after_script( array() );
42
+ }
43
+ }
44
+ }
45
  add_action( 'seedprod_monsterinsights_output_tracking', 'monsterinsights_seedprod_tracking', 6, 1 );
includes/frontend/tracking/class-tracking-analytics.php CHANGED
@@ -1,336 +1,336 @@
1
- <?php
2
- /**
3
- * Tracking analytics.js class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
- class MonsterInsights_Tracking_Analytics extends MonsterInsights_Tracking_Abstract {
17
-
18
- /**
19
- * Holds the name of the tracking type.
20
- *
21
- * @since 6.0.0
22
- * @access public
23
- *
24
- * @var string $name Name of the tracking type.
25
- */
26
- public $name = 'analytics';
27
-
28
- /**
29
- * Version of the tracking class.
30
- *
31
- * @since 6.0.0
32
- * @access public
33
- *
34
- * @var string $version Version of the tracking class.
35
- */
36
- public $version = '1.0.0';
37
-
38
- /**
39
- * Primary class constructor.
40
- *
41
- * @since 6.0.0
42
- * @access public
43
- */
44
- public function __construct() {
45
-
46
- }
47
-
48
- /**
49
- * Get frontend tracking options.
50
- *
51
- * This function is used to return an array of parameters
52
- * for the frontend_output() function to output. These are
53
- * generally dimensions and turned on GA features.
54
- *
55
- * @since 6.0.0
56
- * @access public
57
- *
58
- * @return array Array of the options to use.
59
- */
60
- public function frontend_tracking_options( ) {
61
- global $wp_query;
62
- $options = array();
63
-
64
- $ua_code = monsterinsights_get_ua_to_output();
65
- if ( empty( $ua_code ) ) {
66
- return $options;
67
- }
68
-
69
- $track_user = monsterinsights_track_user();
70
-
71
- if ( ! $track_user ) {
72
- $options['create'] = "'create', '" . esc_js( $ua_code ) . "', '" . esc_js( 'auto' ) . "'";
73
- $options['forceSSL'] = "'set', 'forceSSL', true";
74
- $options['send'] = "'send','pageview'";
75
- return $options;
76
- }
77
-
78
- $domain = esc_attr( monsterinsights_get_option( 'subdomain_tracking', 'auto' ) );
79
-
80
- $cross_domains = monsterinsights_get_option( 'cross_domains', array() );
81
- $allow_anchor = monsterinsights_get_option( 'allow_anchor', false );
82
-
83
-
84
- $create = array();
85
- if ( $allow_anchor ) {
86
- $create['allowAnchor'] = true;
87
- }
88
-
89
- if ( is_array( $cross_domains ) && ! empty( $cross_domains ) ) {
90
- $create['allowLinker'] = true;
91
- }
92
-
93
- if ( class_exists( 'MonsterInsights_AMP' ) ) {
94
- $create['useAmpClientId'] = true;
95
- }
96
-
97
- $create = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_create', $create );
98
-
99
- if ( $create && ! empty( $create ) && is_array( $create ) ) {
100
- $create = json_encode( $create );
101
- $create = str_replace( '"', "'", $create );
102
- $options['create'] = "'create', '" . esc_js( $ua_code ). "', '" . esc_js( $domain ) . "', " . $create;
103
- } else {
104
- $options['create'] = "'create', '" . esc_js( $ua_code ) . "', '" . esc_js( $domain ) . "'";
105
- }
106
-
107
- $options['forceSSL'] = "'set', 'forceSSL', true";
108
-
109
- $code = monsterinsights_get_option( 'custom_code', false );
110
- if ( ! empty( $code ) ) {
111
- // Add custom code to the view
112
- $options['custom_code'] = array(
113
- 'type' => 'custom_code',
114
- 'value' => stripslashes( $code ),
115
- );
116
- }
117
-
118
- // Anonymous data
119
- if ( monsterinsights_get_option( 'anonymize_ips', false ) ) {
120
- $options['anonymize_ips'] = "'set', 'anonymizeIp', true";
121
- }
122
-
123
- $options = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_before_scripts', $options );
124
-
125
- // add demographics
126
- if ( monsterinsights_get_option( 'demographics', false ) ) {
127
- $options['demographics'] = "'require', 'displayfeatures'";
128
- }
129
-
130
- // Add Enhanced link attribution.
131
- if ( monsterinsights_get_option( 'enhanced_link_attribution', false ) ) {
132
- $options['enhanced_link_attribution'] = "'require', 'linkid', 'linkid.js'";
133
- }
134
-
135
- // Add cross-domain tracking.
136
- if ( is_array( $cross_domains ) && ! empty( $cross_domains ) ) {
137
- $options['cross_domain_tracking'] = "'require', 'linker'";
138
- $cross_domains_strings = array();
139
- foreach ( $cross_domains as $cross_domain ) {
140
- if ( ! isset( $cross_domain['domain'] ) ) {
141
- continue;
142
- }
143
- $cross_domains_strings[] = '\'' . $cross_domain['domain'] . '\'';
144
- }
145
- if ( ! empty( $cross_domains_strings ) ) {
146
- $cross_domains_strings = implode( ',', $cross_domains_strings );
147
- $options['cross_domains'] = "'linker:autoLink', [$cross_domains_strings]";
148
- }
149
- }
150
-
151
- $options = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_before_pageview', $options );
152
- $options = apply_filters( 'monsterinsights_frontend_tracking_options_before_pageview', $options, $this->name, $this->version );
153
-
154
- if ( is_404() ) {
155
- if ( monsterinsights_get_option( 'hash_tracking', false ) ) {
156
- $options['send'] = "'send','pageview','/404.html?page=' + document.location.pathname + document.location.search + location.hash + '&from=' + document.referrer";
157
- } else {
158
- $options['send'] = "'send','pageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
159
- }
160
- } else if ( $wp_query->is_search ) {
161
- $pushstr = "'send','pageview','/?s=";
162
- if ( (int) $wp_query->found_posts === 0 ) {
163
- $options['send'] = $pushstr . 'no-results:' . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
164
- } else if ( (int) $wp_query->found_posts === 1 ) {
165
- $options['send'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
166
- } else if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
167
- $options['send'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
168
- } else {
169
- $options['send'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
170
- }
171
- } else if ( monsterinsights_get_option( 'hash_tracking', false ) ) {
172
- $options['send'] = "'send','pageview', location.pathname + location.search + location.hash";
173
- } else {
174
- $options['send'] = "'send','pageview'";
175
- }
176
-
177
- $options = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_end', $options );
178
- return $options;
179
- }
180
-
181
- /**
182
- * Get frontend output.
183
- *
184
- * This function is used to return the Javascript
185
- * to output in the head of the page for the given
186
- * tracking method.
187
- *
188
- * @since 6.0.0
189
- * @access public
190
- *
191
- * @return string Javascript to output.
192
- */
193
- public function frontend_output( ) {
194
- $options = $this->frontend_tracking_options();
195
- $src = apply_filters( 'monsterinsights_frontend_output_analytics_src', '//www.google-analytics.com/analytics.js' );
196
- $compat = monsterinsights_get_option( 'gatracker_compatibility_mode', false );
197
- $compat = $compat ? 'window.ga = __gaTracker;' : '';
198
- $track_user = monsterinsights_track_user();
199
- $ua = monsterinsights_get_ua();
200
- $output = '';
201
- $reason = '';
202
- $attributes = apply_filters( 'monsterinsights_tracking_analytics_script_attributes', array( 'type' => "text/javascript", 'data-cfasync' => 'false' ) );
203
- $attr_string = '';
204
- if ( ! empty( $attributes ) ) {
205
- foreach( $attributes as $attr_name => $attr_value ) {
206
- if ( ! empty( $attr_name ) ) {
207
- $attr_string .= ' ' . sanitize_key( $attr_name ) . '="' . esc_attr( $attr_value ) . '"';
208
- } else {
209
- $attr_string .= ' ' . sanitize_key( $attr_value );
210
- }
211
- }
212
- }
213
- ob_start();
214
- ?>
215
- <!-- This site uses the Google Analytics by MonsterInsights plugin v<?php echo MONSTERINSIGHTS_VERSION; ?> - Using Analytics tracking - https://www.monsterinsights.com/ -->
216
- <?php if ( ! $track_user ) {
217
- if ( empty( $ua ) ) {
218
- $reason = __( 'Note: MonsterInsights is not currently configured on this site. The site owner needs to authenticate with Google Analytics in the MonsterInsights settings panel.', 'google-analytics-for-wordpress' );
219
- $output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
220
- } else if ( current_user_can( 'monsterinsights_save_settings' ) ) {
221
- $reason = __( 'Note: MonsterInsights does not track you as a logged in site administrator to prevent site owners from accidentally skewing their own Google Analytics data.'. PHP_EOL . 'If you are testing Google Analytics code, please do so either logged out or in the private browsing/incognito mode of your web browser.', 'google-analytics-for-wordpress' );
222
- $output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
223
- } else {
224
- $reason = __( 'Note: The site owner has disabled Google Analytics tracking for your user role.', 'google-analytics-for-wordpress' );
225
- $output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
226
- }
227
- echo $output;
228
- } ?>
229
- <?php if ( $ua ) { ?>
230
- <script<?php echo $attr_string;?>>
231
- var mi_version = '<?php echo MONSTERINSIGHTS_VERSION; ?>';
232
- var mi_track_user = <?php echo ( $track_user ? 'true' : 'false' ); ?>;
233
- var mi_no_track_reason = <?php echo ( $reason ? "'" . esc_js( $reason) . "'": "''" ); ?>;
234
- <?php do_action( 'monsterinsights_tracking_analytics_frontend_output_after_mi_track_user' ); ?>
235
-
236
- <?php if ( $this->should_do_optout() ) { ?>
237
- var disableStr = 'ga-disable-<?php echo monsterinsights_get_ua(); ?>';
238
-
239
- /* Function to detect opted out users */
240
- function __gaTrackerIsOptedOut() {
241
- return document.cookie.indexOf(disableStr + '=true') > -1;
242
- }
243
-
244
- /* Disable tracking if the opt-out cookie exists. */
245
- if ( __gaTrackerIsOptedOut() ) {
246
- window[disableStr] = true;
247
- }
248
-
249
- /* Opt-out function */
250
- function __gaTrackerOptout() {
251
- document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';
252
- window[disableStr] = true;
253
- }
254
- <?php } ?>
255
-
256
- if ( mi_track_user ) {
257
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
258
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
259
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
260
- })(window,document,'script','<?php echo $src; ?>','__gaTracker');
261
-
262
- <?php
263
- echo $compat;
264
-
265
- if ( count( $options ) >= 1 ) {
266
- foreach ( $options as $item ) {
267
- if ( ! is_array( $item ) ) {
268
- echo ' __gaTracker(' . $item . ");\n";
269
- } else if ( ! empty ( $item['value'] ) ) {
270
- echo ' ' . $item['value'] . "\n";
271
- }
272
- }
273
- }
274
- ?>
275
- } else {
276
- <?php if ( $this->should_do_optout() ) { ?>
277
- console.log( "<?php echo esc_js( $reason );?>" );
278
- (function() {
279
- /* https://developers.google.com/analytics/devguides/collection/analyticsjs/ */
280
- var noopfn = function() {
281
- return null;
282
- };
283
- var noopnullfn = function() {
284
- return null;
285
- };
286
- var Tracker = function() {
287
- return null;
288
- };
289
- var p = Tracker.prototype;
290
- p.get = noopfn;
291
- p.set = noopfn;
292
- p.send = noopfn;
293
- var __gaTracker = function() {
294
- var len = arguments.length;
295
- if ( len === 0 ) {
296
- return;
297
- }
298
- var f = arguments[len-1];
299
- if ( typeof f !== 'object' || f === null || typeof f.hitCallback !== 'function' ) {
300
- console.log( '<?php echo esc_js( __("Not running function", "google-analytics-for-wordpress" ) );?> __gaTracker(' + arguments[0] + " ....) <?php echo esc_js( __( "because you are not being tracked.", 'google-analytics-for-wordpress' ) );?> " + mi_no_track_reason );
301
- return;
302
- }
303
- try {
304
- f.hitCallback();
305
- } catch (ex) {
306
-
307
- }
308
- };
309
- __gaTracker.create = function() {
310
- return new Tracker();
311
- };
312
- __gaTracker.getByName = noopnullfn;
313
- __gaTracker.getAll = function() {
314
- return [];
315
- };
316
- __gaTracker.remove = noopfn;
317
- window['__gaTracker'] = __gaTracker;
318
- <?php echo $compat; ?>
319
- })();
320
- <?php } ?>
321
- }
322
- </script>
323
- <?php } else { ?>
324
- <!-- No UA code set -->
325
- <?php } ?>
326
- <!-- / Google Analytics by MonsterInsights -->
327
- <?php
328
- $output = ob_get_contents();
329
- ob_end_clean();
330
- return $output;
331
- }
332
-
333
- public function should_do_optout() {
334
- return ! ( defined( 'MI_NO_TRACKING_OPTOUT' ) && MI_NO_TRACKING_OPTOUT );
335
- }
336
- }
1
+ <?php
2
+ /**
3
+ * Tracking analytics.js class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ class MonsterInsights_Tracking_Analytics extends MonsterInsights_Tracking_Abstract {
17
+
18
+ /**
19
+ * Holds the name of the tracking type.
20
+ *
21
+ * @since 6.0.0
22
+ * @access public
23
+ *
24
+ * @var string $name Name of the tracking type.
25
+ */
26
+ public $name = 'analytics';
27
+
28
+ /**
29
+ * Version of the tracking class.
30
+ *
31
+ * @since 6.0.0
32
+ * @access public
33
+ *
34
+ * @var string $version Version of the tracking class.
35
+ */
36
+ public $version = '1.0.0';
37
+
38
+ /**
39
+ * Primary class constructor.
40
+ *
41
+ * @since 6.0.0
42
+ * @access public
43
+ */
44
+ public function __construct() {
45
+
46
+ }
47
+
48
+ /**
49
+ * Get frontend tracking options.
50
+ *
51
+ * This function is used to return an array of parameters
52
+ * for the frontend_output() function to output. These are
53
+ * generally dimensions and turned on GA features.
54
+ *
55
+ * @since 6.0.0
56
+ * @access public
57
+ *
58
+ * @return array Array of the options to use.
59
+ */
60
+ public function frontend_tracking_options( ) {
61
+ global $wp_query;
62
+ $options = array();
63
+
64
+ $ua_code = monsterinsights_get_ua_to_output();
65
+ if ( empty( $ua_code ) ) {
66
+ return $options;
67
+ }
68
+
69
+ $track_user = monsterinsights_track_user();
70
+
71
+ if ( ! $track_user ) {
72
+ $options['create'] = "'create', '" . esc_js( $ua_code ) . "', '" . esc_js( 'auto' ) . "'";
73
+ $options['forceSSL'] = "'set', 'forceSSL', true";
74
+ $options['send'] = "'send','pageview'";
75
+ return $options;
76
+ }
77
+
78
+ $domain = esc_attr( monsterinsights_get_option( 'subdomain_tracking', 'auto' ) );
79
+
80
+ $cross_domains = monsterinsights_get_option( 'cross_domains', array() );
81
+ $allow_anchor = monsterinsights_get_option( 'allow_anchor', false );
82
+
83
+
84
+ $create = array();
85
+ if ( $allow_anchor ) {
86
+ $create['allowAnchor'] = true;
87
+ }
88
+
89
+ if ( is_array( $cross_domains ) && ! empty( $cross_domains ) ) {
90
+ $create['allowLinker'] = true;
91
+ }
92
+
93
+ if ( class_exists( 'MonsterInsights_AMP' ) ) {
94
+ $create['useAmpClientId'] = true;
95
+ }
96
+
97
+ $create = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_create', $create );
98
+
99
+ if ( $create && ! empty( $create ) && is_array( $create ) ) {
100
+ $create = json_encode( $create );
101
+ $create = str_replace( '"', "'", $create );
102
+ $options['create'] = "'create', '" . esc_js( $ua_code ). "', '" . esc_js( $domain ) . "', " . $create;
103
+ } else {
104
+ $options['create'] = "'create', '" . esc_js( $ua_code ) . "', '" . esc_js( $domain ) . "'";
105
+ }
106
+
107
+ $options['forceSSL'] = "'set', 'forceSSL', true";
108
+
109
+ $code = monsterinsights_get_option( 'custom_code', false );
110
+ if ( ! empty( $code ) ) {
111
+ // Add custom code to the view
112
+ $options['custom_code'] = array(
113
+ 'type' => 'custom_code',
114
+ 'value' => stripslashes( $code ),
115
+ );
116
+ }
117
+
118
+ // Anonymous data
119
+ if ( monsterinsights_get_option( 'anonymize_ips', false ) ) {
120
+ $options['anonymize_ips'] = "'set', 'anonymizeIp', true";
121
+ }
122
+
123
+ $options = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_before_scripts', $options );
124
+
125
+ // add demographics
126
+ if ( monsterinsights_get_option( 'demographics', false ) ) {
127
+ $options['demographics'] = "'require', 'displayfeatures'";
128
+ }
129
+
130
+ // Add Enhanced link attribution.
131
+ if ( monsterinsights_get_option( 'enhanced_link_attribution', false ) ) {
132
+ $options['enhanced_link_attribution'] = "'require', 'linkid', 'linkid.js'";
133
+ }
134
+
135
+ // Add cross-domain tracking.
136
+ if ( is_array( $cross_domains ) && ! empty( $cross_domains ) ) {
137
+ $options['cross_domain_tracking'] = "'require', 'linker'";
138
+ $cross_domains_strings = array();
139
+ foreach ( $cross_domains as $cross_domain ) {
140
+ if ( ! isset( $cross_domain['domain'] ) ) {
141
+ continue;
142
+ }
143
+ $cross_domains_strings[] = '\'' . $cross_domain['domain'] . '\'';
144
+ }
145
+ if ( ! empty( $cross_domains_strings ) ) {
146
+ $cross_domains_strings = implode( ',', $cross_domains_strings );
147
+ $options['cross_domains'] = "'linker:autoLink', [$cross_domains_strings]";
148
+ }
149
+ }
150
+
151
+ $options = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_before_pageview', $options );
152
+ $options = apply_filters( 'monsterinsights_frontend_tracking_options_before_pageview', $options, $this->name, $this->version );
153
+
154
+ if ( is_404() ) {
155
+ if ( monsterinsights_get_option( 'hash_tracking', false ) ) {
156
+ $options['send'] = "'send','pageview','/404.html?page=' + document.location.pathname + document.location.search + location.hash + '&from=' + document.referrer";
157
+ } else {
158
+ $options['send'] = "'send','pageview','/404.html?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer";
159
+ }
160
+ } else if ( $wp_query->is_search ) {
161
+ $pushstr = "'send','pageview','/?s=";
162
+ if ( (int) $wp_query->found_posts === 0 ) {
163
+ $options['send'] = $pushstr . 'no-results:' . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
164
+ } else if ( (int) $wp_query->found_posts === 1 ) {
165
+ $options['send'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
166
+ } else if ( $wp_query->found_posts > 1 && $wp_query->found_posts < 6 ) {
167
+ $options['send'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=2-5-results'";
168
+ } else {
169
+ $options['send'] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=plus-5-results'";
170
+ }
171
+ } else if ( monsterinsights_get_option( 'hash_tracking', false ) ) {
172
+ $options['send'] = "'send','pageview', location.pathname + location.search + location.hash";
173
+ } else {
174
+ $options['send'] = "'send','pageview'";
175
+ }
176
+
177
+ $options = apply_filters( 'monsterinsights_frontend_tracking_options_analytics_end', $options );
178
+ return $options;
179
+ }
180
+
181
+ /**
182
+ * Get frontend output.
183
+ *
184
+ * This function is used to return the Javascript
185
+ * to output in the head of the page for the given
186
+ * tracking method.
187
+ *
188
+ * @since 6.0.0
189
+ * @access public
190
+ *
191
+ * @return string Javascript to output.
192
+ */
193
+ public function frontend_output( ) {
194
+ $options = $this->frontend_tracking_options();
195
+ $src = apply_filters( 'monsterinsights_frontend_output_analytics_src', '//www.google-analytics.com/analytics.js' );
196
+ $compat = monsterinsights_get_option( 'gatracker_compatibility_mode', false );
197
+ $compat = $compat ? 'window.ga = __gaTracker;' : '';
198
+ $track_user = monsterinsights_track_user();
199
+ $ua = monsterinsights_get_ua();
200
+ $output = '';
201
+ $reason = '';
202
+ $attributes = apply_filters( 'monsterinsights_tracking_analytics_script_attributes', array( 'type' => "text/javascript", 'data-cfasync' => 'false' ) );
203
+ $attr_string = '';
204
+ if ( ! empty( $attributes ) ) {
205
+ foreach( $attributes as $attr_name => $attr_value ) {
206
+ if ( ! empty( $attr_name ) ) {
207
+ $attr_string .= ' ' . sanitize_key( $attr_name ) . '="' . esc_attr( $attr_value ) . '"';
208
+ } else {
209
+ $attr_string .= ' ' . sanitize_key( $attr_value );
210
+ }
211
+ }
212
+ }
213
+ ob_start();
214
+ ?>
215
+ <!-- This site uses the Google Analytics by MonsterInsights plugin v<?php echo MONSTERINSIGHTS_VERSION; ?> - Using Analytics tracking - https://www.monsterinsights.com/ -->
216
+ <?php if ( ! $track_user ) {
217
+ if ( empty( $ua ) ) {
218
+ $reason = __( 'Note: MonsterInsights is not currently configured on this site. The site owner needs to authenticate with Google Analytics in the MonsterInsights settings panel.', 'google-analytics-for-wordpress' );
219
+ $output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
220
+ } else if ( current_user_can( 'monsterinsights_save_settings' ) ) {
221
+ $reason = __( 'Note: MonsterInsights does not track you as a logged in site administrator to prevent site owners from accidentally skewing their own Google Analytics data.'. PHP_EOL . 'If you are testing Google Analytics code, please do so either logged out or in the private browsing/incognito mode of your web browser.', 'google-analytics-for-wordpress' );
222
+ $output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
223
+ } else {
224
+ $reason = __( 'Note: The site owner has disabled Google Analytics tracking for your user role.', 'google-analytics-for-wordpress' );
225
+ $output .= '<!-- ' . esc_html( $reason ) . ' -->' . PHP_EOL;
226
+ }
227
+ echo $output;
228
+ } ?>
229
+ <?php if ( $ua ) { ?>
230
+ <script<?php echo $attr_string;?>>
231
+ var mi_version = '<?php echo MONSTERINSIGHTS_VERSION; ?>';
232
+ var mi_track_user = <?php echo ( $track_user ? 'true' : 'false' ); ?>;
233
+ var mi_no_track_reason = <?php echo ( $reason ? "'" . esc_js( $reason) . "'": "''" ); ?>;
234
+ <?php do_action( 'monsterinsights_tracking_analytics_frontend_output_after_mi_track_user' ); ?>
235
+
236
+ <?php if ( $this->should_do_optout() ) { ?>
237
+ var disableStr = 'ga-disable-<?php echo monsterinsights_get_ua(); ?>';
238
+
239
+ /* Function to detect opted out users */
240
+ function __gaTrackerIsOptedOut() {
241
+ return document.cookie.indexOf(disableStr + '=true') > -1;
242
+ }
243
+
244
+ /* Disable tracking if the opt-out cookie exists. */
245
+ if ( __gaTrackerIsOptedOut() ) {
246
+ window[disableStr] = true;
247
+ }
248
+
249
+ /* Opt-out function */
250
+ function __gaTrackerOptout() {
251
+ document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';
252
+ window[disableStr] = true;
253
+ }
254
+ <?php } ?>
255
+
256
+ if ( mi_track_user ) {
257
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
258
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
259
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
260
+ })(window,document,'script','<?php echo $src; ?>','__gaTracker');
261
+
262
+ <?php
263
+ echo $compat;
264
+
265
+ if ( count( $options ) >= 1 ) {
266
+ foreach ( $options as $item ) {
267
+ if ( ! is_array( $item ) ) {
268
+ echo ' __gaTracker(' . $item . ");\n";
269
+ } else if ( ! empty ( $item['value'] ) ) {
270
+ echo ' ' . $item['value'] . "\n";
271
+ }
272
+ }
273
+ }
274
+ ?>
275
+ } else {
276
+ <?php if ( $this->should_do_optout() ) { ?>
277
+ console.log( "<?php echo esc_js( $reason );?>" );
278
+ (function() {
279
+ /* https://developers.google.com/analytics/devguides/collection/analyticsjs/ */
280
+ var noopfn = function() {
281
+ return null;
282
+ };
283
+ var noopnullfn = function() {
284
+ return null;
285
+ };
286
+ var Tracker = function() {
287
+ return null;
288
+ };
289
+ var p = Tracker.prototype;
290
+ p.get = noopfn;
291
+ p.set = noopfn;
292
+ p.send = noopfn;
293
+ var __gaTracker = function() {
294
+ var len = arguments.length;
295
+ if ( len === 0 ) {
296
+ return;
297
+ }
298
+ var f = arguments[len-1];
299
+ if ( typeof f !== 'object' || f === null || typeof f.hitCallback !== 'function' ) {
300
+ console.log( '<?php echo esc_js( __("Not running function", "google-analytics-for-wordpress" ) );?> __gaTracker(' + arguments[0] + " ....) <?php echo esc_js( __( "because you are not being tracked.", 'google-analytics-for-wordpress' ) );?> " + mi_no_track_reason );
301
+ return;
302
+ }
303
+ try {
304
+ f.hitCallback();
305
+ } catch (ex) {
306
+
307
+ }
308
+ };
309
+ __gaTracker.create = function() {
310
+ return new Tracker();
311
+ };
312
+ __gaTracker.getByName = noopnullfn;
313
+ __gaTracker.getAll = function() {
314
+ return [];
315
+ };
316
+ __gaTracker.remove = noopfn;
317
+ window['__gaTracker'] = __gaTracker;
318
+ <?php echo $compat; ?>
319
+ })();
320
+ <?php } ?>
321
+ }
322
+ </script>
323
+ <?php } else { ?>
324
+ <!-- No UA code set -->
325
+ <?php } ?>
326
+ <!-- / Google Analytics by MonsterInsights -->
327
+ <?php
328
+ $output = ob_get_contents();
329
+ ob_end_clean();
330
+ return $output;
331
+ }
332
+
333
+ public function should_do_optout() {
334
+ return ! ( defined( 'MI_NO_TRACKING_OPTOUT' ) && MI_NO_TRACKING_OPTOUT );
335
+ }
336
+ }
includes/frontend/tracking/class-tracking-preview.php CHANGED
@@ -1,81 +1,81 @@
1
- <?php
2
- /**
3
- * Tracking debug class.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @author Chris Christoff
9
- */
10
-
11
- // Exit if accessed directly
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
-
16
- class MonsterInsights_Tracking_Preview extends MonsterInsights_Tracking_Abstract {
17
- /**
18
- * Holds the name of the tracking type.
19
- *
20
- * @since 6.0.0
21
- * @access public
22
- *
23
- * @var string $name Name of the tracking type.
24
- */
25
- public $name = 'preview';
26
-
27
- /**
28
- * Version of the tracking class.
29
- *
30
- * @since 6.0.0
31
- * @access public
32
- *
33
- * @var string $version Version of the tracking class.
34
- */
35
- public $version = '1.0.0';
36
-
37
- /**
38
- * Primary class constructor.
39
- *
40
- * @since 6.0.0
41
- * @access public
42
- */
43
- public function __construct() {
44
-
45
- }
46
-
47
- /**
48
- * Get frontend tracking options.
49
- *
50
- * This function is used to return an array of parameters
51
- * for the frontend_output() function to output. These are
52
- * generally dimensions and turned on GA features.
53
- *
54
- * @since 6.0.0
55
- * @access public
56
- *
57
- * @return array Array of the options to use.
58
- */
59
- public function frontend_tracking_options( ) {
60
- return array();
61
- }
62
-
63
- /**
64
- * Get frontend output.
65
- *
66
- * This function is used to return the Javascript
67
- * to output in the head of the page for the given
68
- * tracking method.
69
- *
70
- * @since 6.0.0
71
- * @access public
72
- *
73
- * @return string Javascript to output.
74
- */
75
- public function frontend_output( ) {
76
- $output = '<!-- This site uses the Google Analytics by MonsterInsights plugin v ' . MONSTERINSIGHTS_VERSION .' - https://www.monsterinsights.com/ -->';
77
- $output .= '<!-- ' . esc_html__( "You are currently in a preview window. MonsterInsights doesn't track preview window traffic to avoid false visit reports.", 'google-analytics-for-wordpress' ) . ' -->';
78
- $output .= '<!-- / Google Analytics by MonsterInsights -->';
79
- return $output;
80
- }
81
  }
1
+ <?php
2
+ /**
3
+ * Tracking debug class.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @author Chris Christoff
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
15
+
16
+ class MonsterInsights_Tracking_Preview extends MonsterInsights_Tracking_Abstract {
17
+ /**
18
+ * Holds the name of the tracking type.
19
+ *
20
+ * @since 6.0.0
21
+ * @access public
22
+ *
23
+ * @var string $name Name of the tracking type.
24
+ */
25
+ public $name = 'preview';
26
+
27
+ /**
28
+ * Version of the tracking class.
29
+ *
30
+ * @since 6.0.0
31
+ * @access public
32
+ *
33
+ * @var string $version Version of the tracking class.
34
+ */
35
+ public $version = '1.0.0';
36
+
37
+ /**
38
+ * Primary class constructor.
39
+ *
40
+ * @since 6.0.0
41
+ * @access public
42
+ */
43
+ public function __construct() {
44
+
45
+ }
46
+
47
+ /**
48
+ * Get frontend tracking options.
49
+ *
50
+ * This function is used to return an array of parameters
51
+ * for the frontend_output() function to output. These are
52
+ * generally dimensions and turned on GA features.
53
+ *
54
+ * @since 6.0.0
55
+ * @access public
56
+ *
57
+ * @return array Array of the options to use.
58
+ */
59
+ public function frontend_tracking_options( ) {
60
+ return array();
61
+ }
62
+
63
+ /**
64
+ * Get frontend output.
65
+ *
66
+ * This function is used to return the Javascript
67
+ * to output in the head of the page for the given
68
+ * tracking method.
69
+ *
70
+ * @since 6.0.0
71
+ * @access public
72
+ *
73
+ * @return string Javascript to output.
74
+ */
75
+ public function frontend_output( ) {
76
+ $output = '<!-- This site uses the Google Analytics by MonsterInsights plugin v ' . MONSTERINSIGHTS_VERSION .' - https://www.monsterinsights.com/ -->';
77
+ $output .= '<!-- ' . esc_html__( "You are currently in a preview window. MonsterInsights doesn't track preview window traffic to avoid false visit reports.", 'google-analytics-for-wordpress' ) . ' -->';
78
+ $output .= '<!-- / Google Analytics by MonsterInsights -->';
79
+ return $output;
80
+ }
81
  }
includes/frontend/tracking/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
includes/helpers.php CHANGED
@@ -1,1179 +1,1242 @@
1
- <?php
2
- /**
3
- * Helper functions.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Helper
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- function monsterinsights_is_page_reload() {
18
- // Can't be a refresh without having a referrer
19
- if ( ! isset( $_SERVER['HTTP_REFERER'] ) ) {
20
- return false;
21
- }
22
-
23
- // IF the referrer is identical to the current page request, then it's a refresh
24
- return ( parse_url( $_SERVER['HTTP_REFERER'], PHP_URL_PATH ) === parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ) );
25
- }
26
-
27
-
28
- function monsterinsights_track_user( $user_id = -1 ) {
29
- if ( $user_id === -1 ) {
30
- $user = wp_get_current_user();
31
- } else {
32
- $user = new WP_User( $user_id );
33
- }
34
-
35
- $track_user = true;
36
- $roles = monsterinsights_get_option( 'ignore_users', array() );
37
-
38
- if ( ! empty( $roles ) && is_array( $roles ) ) {
39
- foreach ( $roles as $role ) {
40
- if ( is_string( $role ) ) {
41
- if ( user_can( $user, $role ) ) {
42
- $track_user = false;
43
- break;
44
- }
45
- }
46
- }
47
- }
48
-
49
- $track_super_admin = apply_filters( 'monsterinsights_track_super_admins', false );
50
- if ( $track_super_admin === false && is_multisite() && is_super_admin() ) {
51
- $track_user = false;
52
- }
53
-
54
- // or if UA code is not entered
55
- $ua_code = monsterinsights_get_ua();
56
- if ( empty( $ua_code ) ) {
57
- $track_user = false;
58
- }
59
-
60
- return apply_filters( 'monsterinsights_track_user', $track_user, $user );
61
- }
62
-
63
- function monsterinsights_get_client_id( $payment_id = false ) {
64
- if ( is_object( $payment_id ) ) {
65
- $payment_id = $payment_id->ID;
66
- }
67
- $user_cid = monsterinsights_get_uuid();
68
- $saved_cid = ! empty( $payment_id ) ? get_post_meta( $payment_id, '_yoast_gau_uuid', true ) : false;
69
-
70
- if ( ! empty( $payment_id ) && ! empty( $saved_cid ) ) {
71
- return $saved_cid;
72
- } else if ( ! empty( $user_cid ) ) {
73
- return $user_cid;
74
- } else {
75
- return monsterinsights_generate_uuid();
76
- }
77
- }
78
-
79
- /**
80
- * Returns the Google Analytics clientId to store for later use
81
- *
82
- * @since 6.0.0
83
- *
84
- * @link https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#getClientId
85
- *
86
- * @return bool|string False if cookie isn't set, GA UUID otherwise
87
- */
88
- function monsterinsights_get_uuid() {
89
- if ( empty( $_COOKIE['_ga'] ) ) {
90
- return false;
91
- }
92
-
93
- /**
94
- * Example cookie formats:
95
- *
96
- * GA1.2.XXXXXXX.YYYYY
97
- * _ga=1.2.XXXXXXX.YYYYYY -- We want the XXXXXXX.YYYYYY part
98
- *
99
- */
100
-
101
- $ga_cookie = $_COOKIE['_ga'];
102
- $cookie_parts = explode('.', $ga_cookie );
103
- if ( is_array( $cookie_parts ) && ! empty( $cookie_parts[2] ) && ! empty( $cookie_parts[3] ) ) {
104
- $uuid = (string) $cookie_parts[2] . '.' . (string) $cookie_parts[3];
105
- if ( is_string( $uuid ) ) {
106
- return $uuid;
107
- } else {
108
- return false;
109
- }
110
- } else {
111
- return false;
112
- }
113
- }
114
-
115
-
116
- /**
117
- * Generate UUID v4 function - needed to generate a CID when one isn't available
118
- *
119
- * @link http://www.stumiller.me/implementing-google-analytics-measurement-protocol-in-php-and-wordpress/
120
- *
121
- * @since 6.1.8
122
- * @return string
123
- */
124
- function monsterinsights_generate_uuid() {
125
-
126
- return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
127
-
128
- // 32 bits for "time_low"
129
- mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
130
-
131
- // 16 bits for "time_mid"
132
- mt_rand( 0, 0xffff ),
133
-
134
- // 16 bits for "time_hi_and_version",
135
- // four most significant bits holds version number 4
136
- mt_rand( 0, 0x0fff ) | 0x4000,
137
-
138
- // 16 bits, 8 bits for "clk_seq_hi_res",
139
- // 8 bits for "clk_seq_low",
140
- // two most significant bits holds zero and one for variant DCE1.1
141
- mt_rand( 0, 0x3fff ) | 0x8000,
142
-
143
- // 48 bits for "node"
144
- mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
145
- );
146
- }
147
-
148
- /**
149
- * Returns the Google Analytics clientId to store for later use
150
- *
151
- * @since 6.0.0
152
- *
153
- * @return GA UUID or error code.
154
- */
155
- function monsterinsights_get_cookie( $debug = false ) {
156
- if ( empty( $_COOKIE['_ga'] ) ) {
157
- return ( $debug ) ? 'FCE' : false;
158
- }
159
-
160
- $ga_cookie = $_COOKIE['_ga'];
161
- $cookie_parts = explode('.', $ga_cookie );
162
- if ( is_array( $cookie_parts ) && ! empty( $cookie_parts[2] ) && ! empty( $cookie_parts[3] ) ) {
163
- $uuid = (string) $cookie_parts[2] . '.' . (string) $cookie_parts[3];
164
- if ( is_string( $uuid ) ) {
165
- return $ga_cookie;
166
- } else {
167
- return ( $debug ) ? 'FA' : false;
168
- }
169
- } else {
170
- return ( $debug ) ? 'FAE' : false;
171
- }
172
- }
173
-
174
-
175
- function monsterinsights_generate_ga_client_id() {
176
- return rand(100000000,999999999) . '.' . time();
177
- }
178
-
179
-
180
- /**
181
- * Hours between two timestamps.
182
- *
183
- * @access public
184
- * @since 6.0.0
185
- *
186
- * @param string $start Timestamp of start time (in seconds since Unix).
187
- * @param string $stop Timestamp of stop time (in seconds since Unix). Optional. If not used, current_time (in UTC 0 / GMT ) is used.
188
- *
189
- * @return int Hours between the two timestamps, rounded.
190
- */
191
- function monsterinsights_hours_between( $start, $stop = false ) {
192
- if ( $stop === false ) {
193
- $stop = time();
194
- }
195
-
196
- $diff = (int) abs( $stop - $start );
197
- $hours = round( $diff / HOUR_IN_SECONDS );
198
- return $hours;
199
- }
200
-
201
- /**
202
- * Is This MonsterInsights Pro?
203
- *
204
- * We use this function monsterinsights_to determine if the install is a pro version or a lite version install of MonsterInsights.
205
- * If the install is a lite version we disable the install from admin functionality[1] for addons as WordPress.org requires us to,
206
- * we change the links for where to get support (wp.org forum for free; our site for pro), we use this determine what class to load as
207
- * the base class in addons (to avoid fatal errors) and we use this on the system info page to know what constants to display values for
208
- * as the lite and pro versions of our plugin have different constants (and names for those constants) you can declare and use.
209
- *
210
- * [1] Note: This is not "feature-locking" under GPL guidelines but rather something WordPress.org requires us to do to stay
211
- * in compliance with their rules. We wish we didn't have to do this, as in our oppinion this diminishes the user experience
212
- * of users installing our free and premium addons, and we'd love to turn this on for non-Pro installs, but we're not allowed to.
213
- * If WordPress.org ever changes their mind on this subject, we'd totally turn on that feature for Lite installs in a heartbeat.
214
- *
215
- * @todo Are we allowed to turn on admin installing if the user has to manually declare a PHP constant (and thus would not be on
216
- * either by default or via any sort of user interface)? If so, we could add a constant for forcing Pro version so that users can see
217
- * for themselves that we're not feature locking anything inside the plugin + it would make it easier for our team to test stuff (both via
218
- * Travis-CI but also when installing addons to test with the Lite version). Also this would allow for a better user experience for users
219
- * who want that feature.
220
- *
221
- * @since 6.0.0
222
- * @access public
223
- *
224
- * @return bool True if pro version.
225
- */
226
- function monsterinsights_is_pro_version() {
227
- if ( class_exists( 'MonsterInsights' ) ) {
228
- return true;
229
- } else {
230
- return false;
231
- }
232
- }
233
-
234
-
235
- /**
236
- * Get the user roles of this WordPress blog
237
- *
238
- * @return array
239
- */
240
- function monsterinsights_get_roles() {
241
- global $wp_roles;
242
-
243
- $all_roles = $wp_roles->roles;
244
- $roles = array();
245
-
246
- /**
247
- * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
248
- *
249
- * @api array $all_roles
250
- */
251
- $editable_roles = apply_filters( 'editable_roles', $all_roles );
252
-
253
- foreach ( $editable_roles as $id => $name ) {
254
- $roles[ $id ] = translate_user_role( $name['name'] );
255
- }
256
-
257
- return $roles;
258
- }
259
-
260
- /**
261
- * Get the user roles which can manage options. Used to prevent these roles from getting unselected in the settings.
262
- *
263
- * @return array
264
- */
265
- function monsterinsights_get_manage_options_roles() {
266
- global $wp_roles;
267
-
268
- $all_roles = $wp_roles->roles;
269
- $roles = array();
270
-
271
- /**
272
- * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
273
- *
274
- * @api array $all_roles
275
- */
276
- $editable_roles = apply_filters( 'editable_roles', $all_roles );
277
-
278
- foreach ( $editable_roles as $id => $role ) {
279
- if ( isset( $role['capabilities']['manage_options'] ) && $role['capabilities']['manage_options'] ) {
280
- $roles[ $id ] = translate_user_role( $role['name'] );
281
- }
282
- }
283
-
284
- return $roles;
285
- }
286
-
287
- /** Need to escape in advance of passing in $text. */
288
- function monsterinsights_get_message( $type = 'error', $text = '' ) {
289
- $div = '';
290
- if ( $type === 'error' || $type === 'alert' || $type === 'success' || $type === 'info' ) {
291
- $base = MonsterInsights();
292
- return $base->notices->display_inline_notice( 'monsterinsights_standard_notice', '', $text, $type, false, array( 'skip_message_escape' => true ) );
293
- } else {
294
- return '';
295
- }
296
- }
297
-
298
- function monsterinsights_is_dev_url( $url = '' ) {
299
- $is_local_url = false;
300
- // Trim it up
301
- $url = strtolower( trim( $url ) );
302
- // Need to get the host...so let's add the scheme so we can use parse_url
303
- if ( false === strpos( $url, 'http://' ) && false === strpos( $url, 'https://' ) ) {
304
- $url = 'http://' . $url;
305
- }
306
- $url_parts = parse_url( $url );
307
- $host = ! empty( $url_parts['host'] ) ? $url_parts['host'] : false;
308
- if ( ! empty( $url ) && ! empty( $host ) ) {
309
- if ( false !== ip2long( $host ) ) {
310
- if ( ! filter_var( $host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
311
- $is_local_url = true;
312
- }
313
- } else if ( 'localhost' === $host ) {
314
- $is_local_url = true;
315
- }
316
-
317
- $tlds_to_check = array( '.local', ':8888', ':8080', ':8081', '.invalid', '.example', '.test' );
318
- foreach ( $tlds_to_check as $tld ) {
319
- if ( false !== strpos( $host, $tld ) ) {
320
- $is_local_url = true;
321
- break;
322
- }
323
-
324
- }
325
- if ( substr_count( $host, '.' ) > 1 ) {
326
- $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
327
- foreach ( $subdomains_to_check as $subdomain ) {
328
- $subdomain = str_replace( '.', '(.)', $subdomain );
329
- $subdomain = str_replace( array( '*', '(.)' ), '(.*)', $subdomain );
330
- if ( preg_match( '/^(' . $subdomain . ')/', $host ) ) {
331
- $is_local_url = true;
332
- break;
333
- }
334
- }
335
- }
336
- }
337
- return $is_local_url;
338
- }
339
-
340
- // Set cookie to expire in 2 years
341
- function monsterinsights_get_cookie_expiration_date( $time ) {
342
- return date('D, j F Y H:i:s', time() + $time );
343
- }
344
-
345
- function monsterinsights_string_ends_with( $string, $ending ) {
346
- $strlen = strlen($string);
347
- $endinglen = strlen($ending);
348
- if ( $endinglen > $strlen ) {
349
- return false;
350
- }
351
- return substr_compare( $string, $ending, $strlen - $endinglen, $endinglen) === 0;
352
- }
353
-
354
- function monsterinsights_string_starts_with( $string, $start ) {
355
- if ( ! is_string( $string ) || ! is_string( $start ) ) {
356
- return false;
357
- }
358
-
359
- return substr( $string, 0, strlen( $start ) ) === $start;
360
- }
361
-
362
- function monsterinsights_get_country_list( $translated = false ) {
363
- if ( $translated ) {
364
- $countries = array(
365
- '' => '',
366
- 'US' => __( 'United States', 'google-analytics-for-wordpress' ),
367
- 'CA' => __( 'Canada', 'google-analytics-for-wordpress' ),
368
- 'GB' => __( 'United Kingdom', 'google-analytics-for-wordpress' ),
369
- 'AF' => __( 'Afghanistan', 'google-analytics-for-wordpress' ),
370
- 'AX' => __( '&#197;land Islands', 'google-analytics-for-wordpress' ),
371
- 'AL' => __( 'Albania', 'google-analytics-for-wordpress' ),
372
- 'DZ' => __( 'Algeria', 'google-analytics-for-wordpress' ),
373
- 'AS' => __( 'American Samoa', 'google-analytics-for-wordpress' ),
374
- 'AD' => __( 'Andorra', 'google-analytics-for-wordpress' ),
375
- 'AO' => __( 'Angola', 'google-analytics-for-wordpress' ),
376
- 'AI' => __( 'Anguilla', 'google-analytics-for-wordpress' ),
377
- 'AQ' => __( 'Antarctica', 'google-analytics-for-wordpress' ),
378
- 'AG' => __( 'Antigua and Barbuda', 'google-analytics-for-wordpress' ),
379
- 'AR' => __( 'Argentina', 'google-analytics-for-wordpress' ),
380
- 'AM' => __( 'Armenia', 'google-analytics-for-wordpress' ),
381
- 'AW' => __( 'Aruba', 'google-analytics-for-wordpress' ),
382
- 'AU' => __( 'Australia', 'google-analytics-for-wordpress' ),
383
- 'AT' => __( 'Austria', 'google-analytics-for-wordpress' ),
384
- 'AZ' => __( 'Azerbaijan', 'google-analytics-for-wordpress' ),
385
- 'BS' => __( 'Bahamas', 'google-analytics-for-wordpress' ),
386
- 'BH' => __( 'Bahrain', 'google-analytics-for-wordpress' ),
387
- 'BD' => __( 'Bangladesh', 'google-analytics-for-wordpress' ),
388
- 'BB' => __( 'Barbados', 'google-analytics-for-wordpress' ),
389
- 'BY' => __( 'Belarus', 'google-analytics-for-wordpress' ),
390
- 'BE' => __( 'Belgium', 'google-analytics-for-wordpress' ),
391
- 'BZ' => __( 'Belize', 'google-analytics-for-wordpress' ),
392
- 'BJ' => __( 'Benin', 'google-analytics-for-wordpress' ),
393
- 'BM' => __( 'Bermuda', 'google-analytics-for-wordpress' ),
394
- 'BT' => __( 'Bhutan', 'google-analytics-for-wordpress' ),
395
- 'BO' => __( 'Bolivia', 'google-analytics-for-wordpress' ),
396
- 'BQ' => __( 'Bonaire, Saint Eustatius and Saba', 'google-analytics-for-wordpress' ),
397
- 'BA' => __( 'Bosnia and Herzegovina', 'google-analytics-for-wordpress' ),
398
- 'BW' => __( 'Botswana', 'google-analytics-for-wordpress' ),
399
- 'BV' => __( 'Bouvet Island', 'google-analytics-for-wordpress' ),
400
- 'BR' => __( 'Brazil', 'google-analytics-for-wordpress' ),
401
- 'IO' => __( 'British Indian Ocean Territory', 'google-analytics-for-wordpress' ),
402
- 'BN' => __( 'Brunei Darrussalam', 'google-analytics-for-wordpress' ),
403
- 'BG' => __( 'Bulgaria', 'google-analytics-for-wordpress' ),
404
- 'BF' => __( 'Burkina Faso', 'google-analytics-for-wordpress' ),
405
- 'BI' => __( 'Burundi', 'google-analytics-for-wordpress' ),
406
- 'KH' => __( 'Cambodia', 'google-analytics-for-wordpress' ),
407
- 'CM' => __( 'Cameroon', 'google-analytics-for-wordpress' ),
408
- 'CV' => __( 'Cape Verde', 'google-analytics-for-wordpress' ),
409
- 'KY' => __( 'Cayman Islands', 'google-analytics-for-wordpress' ),
410
- 'CF' => __( 'Central African Republic', 'google-analytics-for-wordpress' ),
411
- 'TD' => __( 'Chad', 'google-analytics-for-wordpress' ),
412
- 'CL' => __( 'Chile', 'google-analytics-for-wordpress' ),
413
- 'CN' => __( 'China', 'google-analytics-for-wordpress' ),
414
- 'CX' => __( 'Christmas Island', 'google-analytics-for-wordpress' ),
415
- 'CC' => __( 'Cocos Islands', 'google-analytics-for-wordpress' ),
416
- 'CO' => __( 'Colombia', 'google-analytics-for-wordpress' ),
417
- 'KM' => __( 'Comoros', 'google-analytics-for-wordpress' ),
418
- 'CD' => __( 'Congo, Democratic People\'s Republic', 'google-analytics-for-wordpress' ),
419
- 'CG' => __( 'Congo, Republic of', 'google-analytics-for-wordpress' ),
420
- 'CK' => __( 'Cook Islands', 'google-analytics-for-wordpress' ),
421
- 'CR' => __( 'Costa Rica', 'google-analytics-for-wordpress' ),
422
- 'CI' => __( 'Cote d\'Ivoire', 'google-analytics-for-wordpress' ),
423
- 'HR' => __( 'Croatia/Hrvatska', 'google-analytics-for-wordpress' ),
424
- 'CU' => __( 'Cuba', 'google-analytics-for-wordpress' ),
425
- 'CW' => __( 'Cura&Ccedil;ao', 'google-analytics-for-wordpress' ),
426
- 'CY' => __( 'Cyprus', 'google-analytics-for-wordpress' ),
427
- 'CZ' => __( 'Czechia', 'google-analytics-for-wordpress' ),
428
- 'DK' => __( 'Denmark', 'google-analytics-for-wordpress' ),
429
- 'DJ' => __( 'Djibouti', 'google-analytics-for-wordpress' ),
430
- 'DM' => __( 'Dominica', 'google-analytics-for-wordpress' ),
431
- 'DO' => __( 'Dominican Republic', 'google-analytics-for-wordpress' ),
432
- 'TP' => __( 'East Timor', 'google-analytics-for-wordpress' ),
433
- 'EC' => __( 'Ecuador', 'google-analytics-for-wordpress' ),
434
- 'EG' => __( 'Egypt', 'google-analytics-for-wordpress' ),
435
- 'GQ' => __( 'Equatorial Guinea', 'google-analytics-for-wordpress' ),
436
- 'SV' => __( 'El Salvador', 'google-analytics-for-wordpress' ),
437
- 'ER' => __( 'Eritrea', 'google-analytics-for-wordpress' ),
438
- 'EE' => __( 'Estonia', 'google-analytics-for-wordpress' ),
439
- 'ET' => __( 'Ethiopia', 'google-analytics-for-wordpress' ),
440
- 'FK' => __( 'Falkland Islands', 'google-analytics-for-wordpress' ),
441
- 'FO' => __( 'Faroe Islands', 'google-analytics-for-wordpress' ),
442
- 'FJ' => __( 'Fiji', 'google-analytics-for-wordpress' ),
443
- 'FI' => __( 'Finland', 'google-analytics-for-wordpress' ),
444
- 'FR' => __( 'France', 'google-analytics-for-wordpress' ),
445
- 'GF' => __( 'French Guiana', 'google-analytics-for-wordpress' ),
446
- 'PF' => __( 'French Polynesia', 'google-analytics-for-wordpress' ),
447
- 'TF' => __( 'French Southern Territories', 'google-analytics-for-wordpress' ),
448
- 'GA' => __( 'Gabon', 'google-analytics-for-wordpress' ),
449
- 'GM' => __( 'Gambia', 'google-analytics-for-wordpress' ),
450
- 'GE' => __( 'Georgia', 'google-analytics-for-wordpress' ),
451
- 'DE' => __( 'Germany', 'google-analytics-for-wordpress' ),
452
- 'GR' => __( 'Greece', 'google-analytics-for-wordpress' ),
453
- 'GH' => __( 'Ghana', 'google-analytics-for-wordpress' ),
454
- 'GI' => __( 'Gibraltar', 'google-analytics-for-wordpress' ),
455
- 'GL' => __( 'Greenland', 'google-analytics-for-wordpress' ),
456
- 'GD' => __( 'Grenada', 'google-analytics-for-wordpress' ),
457
- 'GP' => __( 'Guadeloupe', 'google-analytics-for-wordpress' ),
458
- 'GU' => __( 'Guam', 'google-analytics-for-wordpress' ),
459
- 'GT' => __( 'Guatemala', 'google-analytics-for-wordpress' ),
460
- 'GG' => __( 'Guernsey', 'google-analytics-for-wordpress' ),
461
- 'GN' => __( 'Guinea', 'google-analytics-for-wordpress' ),
462
- 'GW' => __( 'Guinea-Bissau', 'google-analytics-for-wordpress' ),
463
- 'GY' => __( 'Guyana', 'google-analytics-for-wordpress' ),
464
- 'HT' => __( 'Haiti', 'google-analytics-for-wordpress' ),
465
- 'HM' => __( 'Heard and McDonald Islands', 'google-analytics-for-wordpress' ),
466
- 'VA' => __( 'Holy See (City Vatican State)', 'google-analytics-for-wordpress' ),
467
- 'HN' => __( 'Honduras', 'google-analytics-for-wordpress' ),
468
- 'HK' => __( 'Hong Kong', 'google-analytics-for-wordpress' ),
469
- 'HU' => __( 'Hungary', 'google-analytics-for-wordpress' ),
470
- 'IS' => __( 'Iceland', 'google-analytics-for-wordpress' ),
471
- 'IN' => __( 'India', 'google-analytics-for-wordpress' ),
472
- 'ID' => __( 'Indonesia', 'google-analytics-for-wordpress' ),
473
- 'IR' => __( 'Iran', 'google-analytics-for-wordpress' ),
474
- 'IQ' => __( 'Iraq', 'google-analytics-for-wordpress' ),
475
- 'IE' => __( 'Ireland', 'google-analytics-for-wordpress' ),
476
- 'IM' => __( 'Isle of Man', 'google-analytics-for-wordpress' ),
477
- 'IL' => __( 'Israel', 'google-analytics-for-wordpress' ),
478
- 'IT' => __( 'Italy', 'google-analytics-for-wordpress' ),
479
- 'JM' => __( 'Jamaica', 'google-analytics-for-wordpress' ),
480
- 'JP' => __( 'Japan', 'google-analytics-for-wordpress' ),
481
- 'JE' => __( 'Jersey', 'google-analytics-for-wordpress' ),
482
- 'JO' => __( 'Jordan', 'google-analytics-for-wordpress' ),
483
- 'KZ' => __( 'Kazakhstan', 'google-analytics-for-wordpress' ),
484
- 'KE' => __( 'Kenya', 'google-analytics-for-wordpress' ),
485
- 'KI' => __( 'Kiribati', 'google-analytics-for-wordpress' ),
486
- 'KW' => __( 'Kuwait', 'google-analytics-for-wordpress' ),
487
- 'KG' => __( 'Kyrgyzstan', 'google-analytics-for-wordpress' ),
488
- 'LA' => __( 'Lao People\'s Democratic Republic', 'google-analytics-for-wordpress' ),
489
- 'LV' => __( 'Latvia', 'google-analytics-for-wordpress' ),
490
- 'LB' => __( 'Lebanon', 'google-analytics-for-wordpress' ),
491
- 'LS' => __( 'Lesotho', 'google-analytics-for-wordpress' ),
492
- 'LR' => __( 'Liberia', 'google-analytics-for-wordpress' ),
493
- 'LY' => __( 'Libyan Arab Jamahiriya', 'google-analytics-for-wordpress' ),
494
- 'LI' => __( 'Liechtenstein', 'google-analytics-for-wordpress' ),
495
- 'LT' => __( 'Lithuania', 'google-analytics-for-wordpress' ),
496
- 'LU' => __( 'Luxembourg', 'google-analytics-for-wordpress' ),
497
- 'MO' => __( 'Macau', 'google-analytics-for-wordpress' ),
498
- 'MK' => __( 'Macedonia (FYROM)', 'google-analytics-for-wordpress' ),
499
- 'MG' => __( 'Madagascar', 'google-analytics-for-wordpress' ),
500
- 'MW' => __( 'Malawi', 'google-analytics-for-wordpress' ),
501
- 'MY' => __( 'Malaysia', 'google-analytics-for-wordpress' ),
502
- 'MV' => __( 'Maldives', 'google-analytics-for-wordpress' ),
503
- 'ML' => __( 'Mali', 'google-analytics-for-wordpress' ),
504
- 'MT' => __( 'Malta', 'google-analytics-for-wordpress' ),
505
- 'MH' => __( 'Marshall Islands', 'google-analytics-for-wordpress' ),
506
- 'MQ' => __( 'Martinique', 'google-analytics-for-wordpress' ),
507
- 'MR' => __( 'Mauritania', 'google-analytics-for-wordpress' ),
508
- 'MU' => __( 'Mauritius', 'google-analytics-for-wordpress' ),
509
- 'YT' => __( 'Mayotte', 'google-analytics-for-wordpress' ),
510
- 'MX' => __( 'Mexico', 'google-analytics-for-wordpress' ),
511
- 'FM' => __( 'Micronesia', 'google-analytics-for-wordpress' ),
512
- 'MD' => __( 'Moldova, Republic of', 'google-analytics-for-wordpress' ),
513
- 'MC' => __( 'Monaco', 'google-analytics-for-wordpress' ),
514
- 'MN' => __( 'Mongolia', 'google-analytics-for-wordpress' ),
515
- 'ME' => __( 'Montenegro', 'google-analytics-for-wordpress' ),
516
- 'MS' => __( 'Montserrat', 'google-analytics-for-wordpress' ),
517
- 'MA' => __( 'Morocco', 'google-analytics-for-wordpress' ),
518
- 'MZ' => __( 'Mozambique', 'google-analytics-for-wordpress' ),
519
- 'MM' => __( 'Myanmar', 'google-analytics-for-wordpress' ),
520
- 'NA' => __( 'Namibia', 'google-analytics-for-wordpress' ),
521
- 'NR' => __( 'Nauru', 'google-analytics-for-wordpress' ),
522
- 'NP' => __( 'Nepal', 'google-analytics-for-wordpress' ),
523
- 'NL' => __( 'Netherlands', 'google-analytics-for-wordpress' ),
524
- 'AN' => __( 'Netherlands Antilles', 'google-analytics-for-wordpress' ),
525
- 'NC' => __( 'New Caledonia', 'google-analytics-for-wordpress' ),
526
- 'NZ' => __( 'New Zealand', 'google-analytics-for-wordpress' ),
527
- 'NI' => __( 'Nicaragua', 'google-analytics-for-wordpress' ),
528
- 'NE' => __( 'Niger', 'google-analytics-for-wordpress' ),
529
- 'NG' => __( 'Nigeria', 'google-analytics-for-wordpress' ),
530
- 'NU' => __( 'Niue', 'google-analytics-for-wordpress' ),
531
- 'NF' => __( 'Norfolk Island', 'google-analytics-for-wordpress' ),
532
- 'KP' => __( 'North Korea', 'google-analytics-for-wordpress' ),
533
- 'MP' => __( 'Northern Mariana Islands', 'google-analytics-for-wordpress' ),
534
- 'NO' => __( 'Norway', 'google-analytics-for-wordpress' ),
535
- 'OM' => __( 'Oman', 'google-analytics-for-wordpress' ),
536
- 'PK' => __( 'Pakistan', 'google-analytics-for-wordpress' ),
537
- 'PW' => __( 'Palau', 'google-analytics-for-wordpress' ),
538
- 'PS' => __( 'Palestinian Territories', 'google-analytics-for-wordpress' ),
539
- 'PA' => __( 'Panama', 'google-analytics-for-wordpress' ),
540
- 'PG' => __( 'Papua New Guinea', 'google-analytics-for-wordpress' ),
541
- 'PY' => __( 'Paraguay', 'google-analytics-for-wordpress' ),
542
- 'PE' => __( 'Peru', 'google-analytics-for-wordpress' ),
543
- 'PH' => __( 'Philippines', 'google-analytics-for-wordpress' ),
544
- 'PN' => __( 'Pitcairn Island', 'google-analytics-for-wordpress' ),
545
- 'PL' => __( 'Poland', 'google-analytics-for-wordpress' ),
546
- 'PT' => __( 'Portugal', 'google-analytics-for-wordpress' ),
547
- 'PR' => __( 'Puerto Rico', 'google-analytics-for-wordpress' ),
548
- 'QA' => __( 'Qatar', 'google-analytics-for-wordpress' ),
549
- 'XK' => __( 'Republic of Kosovo', 'google-analytics-for-wordpress' ),
550
- 'RE' => __( 'Reunion Island', 'google-analytics-for-wordpress' ),
551
- 'RO' => __( 'Romania', 'google-analytics-for-wordpress' ),
552
- 'RU' => __( 'Russian Federation', 'google-analytics-for-wordpress' ),
553
- 'RW' => __( 'Rwanda', 'google-analytics-for-wordpress' ),
554
- 'BL' => __( 'Saint Barth&eacute;lemy', 'google-analytics-for-wordpress' ),
555
- 'SH' => __( 'Saint Helena', 'google-analytics-for-wordpress' ),
556
- 'KN' => __( 'Saint Kitts and Nevis', 'google-analytics-for-wordpress' ),
557
- 'LC' => __( 'Saint Lucia', 'google-analytics-for-wordpress' ),
558
- 'MF' => __( 'Saint Martin (French)', 'google-analytics-for-wordpress' ),
559
- 'SX' => __( 'Saint Martin (Dutch)', 'google-analytics-for-wordpress' ),
560
- 'PM' => __( 'Saint Pierre and Miquelon', 'google-analytics-for-wordpress' ),
561
- 'VC' => __( 'Saint Vincent and the Grenadines', 'google-analytics-for-wordpress' ),
562
- 'SM' => __( 'San Marino', 'google-analytics-for-wordpress' ),
563
- 'ST' => __( 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe', 'google-analytics-for-wordpress' ),
564
- 'SA' => __( 'Saudi Arabia', 'google-analytics-for-wordpress' ),
565
- 'SN' => __( 'Senegal', 'google-analytics-for-wordpress' ),
566
- 'RS' => __( 'Serbia', 'google-analytics-for-wordpress' ),
567
- 'SC' => __( 'Seychelles', 'google-analytics-for-wordpress' ),
568
- 'SL' => __( 'Sierra Leone', 'google-analytics-for-wordpress' ),
569
- 'SG' => __( 'Singapore', 'google-analytics-for-wordpress' ),
570
- 'SK' => __( 'Slovak Republic', 'google-analytics-for-wordpress' ),
571
- 'SI' => __( 'Slovenia', 'google-analytics-for-wordpress' ),
572
- 'SB' => __( 'Solomon Islands', 'google-analytics-for-wordpress' ),
573
- 'SO' => __( 'Somalia', 'google-analytics-for-wordpress' ),
574
- 'ZA' => __( 'South Africa', 'google-analytics-for-wordpress' ),
575
- 'GS' => __( 'South Georgia', 'google-analytics-for-wordpress' ),
576
- 'KR' => __( 'South Korea', 'google-analytics-for-wordpress' ),
577
- 'SS' => __( 'South Sudan', 'google-analytics-for-wordpress' ),
578
- 'ES' => __( 'Spain', 'google-analytics-for-wordpress' ),
579
- 'LK' => __( 'Sri Lanka', 'google-analytics-for-wordpress' ),
580
- 'SD' => __( 'Sudan', 'google-analytics-for-wordpress' ),
581
- 'SR' => __( 'Suriname', 'google-analytics-for-wordpress' ),
582
- 'SJ' => __( 'Svalbard and Jan Mayen Islands', 'google-analytics-for-wordpress' ),
583
- 'SZ' => __( 'Swaziland', 'google-analytics-for-wordpress' ),
584
- 'SE' => __( 'Sweden', 'google-analytics-for-wordpress' ),
585
- 'CH' => __( 'Switzerland', 'google-analytics-for-wordpress' ),
586
- 'SY' => __( 'Syrian Arab Republic', 'google-analytics-for-wordpress' ),
587
- 'TW' => __( 'Taiwan', 'google-analytics-for-wordpress' ),
588
- 'TJ' => __( 'Tajikistan', 'google-analytics-for-wordpress' ),
589
- 'TZ' => __( 'Tanzania', 'google-analytics-for-wordpress' ),
590
- 'TH' => __( 'Thailand', 'google-analytics-for-wordpress' ),
591
- 'TL' => __( 'Timor-Leste', 'google-analytics-for-wordpress' ),
592
- 'TG' => __( 'Togo', 'google-analytics-for-wordpress' ),
593
- 'TK' => __( 'Tokelau', 'google-analytics-for-wordpress' ),
594
- 'TO' => __( 'Tonga', 'google-analytics-for-wordpress' ),
595
- 'TT' => __( 'Trinidad and Tobago', 'google-analytics-for-wordpress' ),
596
- 'TN' => __( 'Tunisia', 'google-analytics-for-wordpress' ),
597
- 'TR' => __( 'Turkey', 'google-analytics-for-wordpress' ),
598
- 'TM' => __( 'Turkmenistan', 'google-analytics-for-wordpress' ),
599
- 'TC' => __( 'Turks and Caicos Islands', 'google-analytics-for-wordpress' ),
600
- 'TV' => __( 'Tuvalu', 'google-analytics-for-wordpress' ),
601
- 'UG' => __( 'Uganda', 'google-analytics-for-wordpress' ),
602
- 'UA' => __( 'Ukraine', 'google-analytics-for-wordpress' ),
603
- 'AE' => __( 'United Arab Emirates', 'google-analytics-for-wordpress' ),
604
- 'UY' => __( 'Uruguay', 'google-analytics-for-wordpress' ),
605
- 'UM' => __( 'US Minor Outlying Islands', 'google-analytics-for-wordpress' ),
606
- 'UZ' => __( 'Uzbekistan', 'google-analytics-for-wordpress' ),
607
- 'VU' => __( 'Vanuatu', 'google-analytics-for-wordpress' ),
608
- 'VE' => __( 'Venezuela', 'google-analytics-for-wordpress' ),
609
- 'VN' => __( 'Vietnam', 'google-analytics-for-wordpress' ),
610
- 'VG' => __( 'Virgin Islands (British)', 'google-analytics-for-wordpress' ),
611
- 'VI' => __( 'Virgin Islands (USA)', 'google-analytics-for-wordpress' ),
612
- 'WF' => __( 'Wallis and Futuna Islands', 'google-analytics-for-wordpress' ),
613
- 'EH' => __( 'Western Sahara', 'google-analytics-for-wordpress' ),
614
- 'WS' => __( 'Western Samoa', 'google-analytics-for-wordpress' ),
615
- 'YE' => __( 'Yemen', 'google-analytics-for-wordpress' ),
616
- 'ZM' => __( 'Zambia', 'google-analytics-for-wordpress' ),
617
- 'ZW' => __( 'Zimbabwe', 'google-analytics-for-wordpress' ),
618
- );
619
- } else {
620
- $countries = array(
621
- '' => '',
622
- 'US' => 'United States',
623
- 'CA' => 'Canada',
624
- 'GB' => 'United Kingdom',
625
- 'AF' => 'Afghanistan',
626
- 'AX' => '&#197;land Islands',
627
- 'AL' => 'Albania',
628
- 'DZ' => 'Algeria',
629
- 'AS' => 'American Samoa',
630
- 'AD' => 'Andorra',
631
- 'AO' => 'Angola',
632
- 'AI' => 'Anguilla',
633
- 'AQ' => 'Antarctica',
634
- 'AG' => 'Antigua and Barbuda',
635
- 'AR' => 'Argentina',
636
- 'AM' => 'Armenia',
637
- 'AW' => 'Aruba',
638
- 'AU' => 'Australia',
639
- 'AT' => 'Austria',
640
- 'AZ' => 'Azerbaijan',
641
- 'BS' => 'Bahamas',
642
- 'BH' => 'Bahrain',
643
- 'BD' => 'Bangladesh',
644
- 'BB' => 'Barbados',
645
- 'BY' => 'Belarus',
646
- 'BE' => 'Belgium',
647
- 'BZ' => 'Belize',
648
- 'BJ' => 'Benin',
649
- 'BM' => 'Bermuda',
650
- 'BT' => 'Bhutan',
651
- 'BO' => 'Bolivia',
652
- 'BQ' => 'Bonaire, Saint Eustatius and Saba',
653
- 'BA' => 'Bosnia and Herzegovina',
654
- 'BW' => 'Botswana',
655
- 'BV' => 'Bouvet Island',
656
- 'BR' => 'Brazil',
657
- 'IO' => 'British Indian Ocean Territory',
658
- 'BN' => 'Brunei Darrussalam',
659
- 'BG' => 'Bulgaria',
660
- 'BF' => 'Burkina Faso',
661
- 'BI' => 'Burundi',
662
- 'KH' => 'Cambodia',
663
- 'CM' => 'Cameroon',
664
- 'CV' => 'Cape Verde',
665
- 'KY' => 'Cayman Islands',
666
- 'CF' => 'Central African Republic',
667
- 'TD' => 'Chad',
668
- 'CL' => 'Chile',
669
- 'CN' => 'China',
670
- 'CX' => 'Christmas Island',
671
- 'CC' => 'Cocos Islands',
672
- 'CO' => 'Colombia',
673
- 'KM' => 'Comoros',
674
- 'CD' => 'Congo, Democratic People\'s Republic',
675
- 'CG' => 'Congo, Republic of',
676
- 'CK' => 'Cook Islands',
677
- 'CR' => 'Costa Rica',
678
- 'CI' => 'Cote d\'Ivoire',
679
- 'HR' => 'Croatia/Hrvatska',
680
- 'CU' => 'Cuba',
681
- 'CW' => 'Cura&Ccedil;ao',
682
- 'CY' => 'Cyprus',
683
- 'CZ' => 'Czechia',
684
- 'DK' => 'Denmark',
685
- 'DJ' => 'Djibouti',
686
- 'DM' => 'Dominica',
687
- 'DO' => 'Dominican Republic',
688
- 'TP' => 'East Timor',
689
- 'EC' => 'Ecuador',
690
- 'EG' => 'Egypt',
691
- 'GQ' => 'Equatorial Guinea',
692
- 'SV' => 'El Salvador',
693
- 'ER' => 'Eritrea',
694
- 'EE' => 'Estonia',
695
- 'ET' => 'Ethiopia',
696
- 'FK' => 'Falkland Islands',
697
- 'FO' => 'Faroe Islands',
698
- 'FJ' => 'Fiji',
699
- 'FI' => 'Finland',
700
- 'FR' => 'France',
701
- 'GF' => 'French Guiana',
702
- 'PF' => 'French Polynesia',
703
- 'TF' => 'French Southern Territories',
704
- 'GA' => 'Gabon',
705
- 'GM' => 'Gambia',
706
- 'GE' => 'Georgia',
707
- 'DE' => 'Germany',
708
- 'GR' => 'Greece',
709
- 'GH' => 'Ghana',
710
- 'GI' => 'Gibraltar',
711
- 'GL' => 'Greenland',
712
- 'GD' => 'Grenada',
713
- 'GP' => 'Guadeloupe',
714
- 'GU' => 'Guam',
715
- 'GT' => 'Guatemala',
716
- 'GG' => 'Guernsey',
717
- 'GN' => 'Guinea',
718
- 'GW' => 'Guinea-Bissau',
719
- 'GY' => 'Guyana',
720
- 'HT' => 'Haiti',
721
- 'HM' => 'Heard and McDonald Islands',
722
- 'VA' => 'Holy See (City Vatican State)',
723
- 'HN' => 'Honduras',
724
- 'HK' => 'Hong Kong',
725
- 'HU' => 'Hungary',
726
- 'IS' => 'Iceland',
727
- 'IN' => 'India',
728
- 'ID' => 'Indonesia',
729
- 'IR' => 'Iran',
730
- 'IQ' => 'Iraq',
731
- 'IE' => 'Ireland',
732
- 'IM' => 'Isle of Man',
733
- 'IL' => 'Israel',
734
- 'IT' => 'Italy',
735
- 'JM' => 'Jamaica',
736
- 'JP' => 'Japan',
737
- 'JE' => 'Jersey',
738
- 'JO' => 'Jordan',
739
- 'KZ' => 'Kazakhstan',
740
- 'KE' => 'Kenya',
741
- 'KI' => 'Kiribati',
742
- 'KW' => 'Kuwait',
743
- 'KG' => 'Kyrgyzstan',
744
- 'LA' => 'Lao People\'s Democratic Republic',
745
- 'LV' => 'Latvia',
746
- 'LB' => 'Lebanon',
747
- 'LS' => 'Lesotho',
748
- 'LR' => 'Liberia',
749
- 'LY' => 'Libyan Arab Jamahiriya',
750
- 'LI' => 'Liechtenstein',
751
- 'LT' => 'Lithuania',
752
- 'LU' => 'Luxembourg',
753
- 'MO' => 'Macau',
754
- 'MK' => 'Macedonia',
755
- 'MG' => 'Madagascar',
756
- 'MW' => 'Malawi',
757
- 'MY' => 'Malaysia',
758
- 'MV' => 'Maldives',
759
- 'ML' => 'Mali',
760
- 'MT' => 'Malta',
761
- 'MH' => 'Marshall Islands',
762
- 'MQ' => 'Martinique',
763
- 'MR' => 'Mauritania',
764
- 'MU' => 'Mauritius',
765
- 'YT' => 'Mayotte',
766
- 'MX' => 'Mexico',
767
- 'FM' => 'Micronesia',
768
- 'MD' => 'Moldova, Republic of',
769
- 'MC' => 'Monaco',
770
- 'MN' => 'Mongolia',
771
- 'ME' => 'Montenegro',
772
- 'MS' => 'Montserrat',
773
- 'MA' => 'Morocco',
774
- 'MZ' => 'Mozambique',
775
- 'MM' => 'Myanmar (Burma)',
776
- 'NA' => 'Namibia',
777
- 'NR' => 'Nauru',
778
- 'NP' => 'Nepal',
779
- 'NL' => 'Netherlands',
780
- 'AN' => 'Netherlands Antilles',
781
- 'NC' => 'New Caledonia',
782
- 'NZ' => 'New Zealand',
783
- 'NI' => 'Nicaragua',
784
- 'NE' => 'Niger',
785
- 'NG' => 'Nigeria',
786
- 'NU' => 'Niue',
787
- 'NF' => 'Norfolk Island',
788
- 'KP' => 'North Korea',
789
- 'MP' => 'Northern Mariana Islands',
790
- 'NO' => 'Norway',
791
- 'OM' => 'Oman',
792
- 'PK' => 'Pakistan',
793
- 'PW' => 'Palau',
794
- 'PS' => 'Palestinian Territories',
795
- 'PA' => 'Panama',
796
- 'PG' => 'Papua New Guinea',
797
- 'PY' => 'Paraguay',
798
- 'PE' => 'Peru',
799
- 'PH' => 'Philippines',
800
- 'PN' => 'Pitcairn Island',
801
- 'PL' => 'Poland',
802
- 'PT' => 'Portugal',
803
- 'PR' => 'Puerto Rico',
804
- 'QA' => 'Qatar',
805
- 'XK' => 'Republic of Kosovo',
806
- 'RE' => 'Reunion Island',
807
- 'RO' => 'Romania',
808
- 'RU' => 'Russia',
809
- 'RW' => 'Rwanda',
810
- 'BL' => 'Saint Barth&eacute;lemy',
811
- 'SH' => 'Saint Helena',
812
- 'KN' => 'Saint Kitts and Nevis',
813
- 'LC' => 'Saint Lucia',
814
- 'MF' => 'Saint Martin (French)',
815
- 'SX' => 'Saint Martin (Dutch)',
816
- 'PM' => 'Saint Pierre and Miquelon',
817
- 'VC' => 'Saint Vincent and the Grenadines',
818
- 'SM' => 'San Marino',
819
- 'ST' => 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe',
820
- 'SA' => 'Saudi Arabia',
821
- 'SN' => 'Senegal',
822
- 'RS' => 'Serbia',
823
- 'SC' => 'Seychelles',
824
- 'SL' => 'Sierra Leone',
825
- 'SG' => 'Singapore',
826
- 'SK' => 'Slovak Republic',
827
- 'SI' => 'Slovenia',
828
- 'SB' => 'Solomon Islands',
829
- 'SO' => 'Somalia',
830
- 'ZA' => 'South Africa',
831
- 'GS' => 'South Georgia',
832
- 'KR' => 'South Korea',
833
- 'SS' => 'South Sudan',
834
- 'ES' => 'Spain',
835
- 'LK' => 'Sri Lanka',
836
- 'SD' => 'Sudan',
837
- 'SR' => 'Suriname',
838
- 'SJ' => 'Svalbard and Jan Mayen Islands',
839
- 'SZ' => 'Swaziland',
840
- 'SE' => 'Sweden',
841
- 'CH' => 'Switzerland',
842
- 'SY' => 'Syrian Arab Republic',
843
- 'TW' => 'Taiwan',
844
- 'TJ' => 'Tajikistan',
845
- 'TZ' => 'Tanzania',
846
- 'TH' => 'Thailand',
847
- 'TL' => 'Timor-Leste',
848
- 'TG' => 'Togo',
849
- 'TK' => 'Tokelau',
850
- 'TO' => 'Tonga',
851
- 'TT' => 'Trinidad and Tobago',
852
- 'TN' => 'Tunisia',
853
- 'TR' => 'Turkey',
854
- 'TM' => 'Turkmenistan',
855
- 'TC' => 'Turks and Caicos Islands',
856
- 'TV' => 'Tuvalu',
857
- 'UG' => 'Uganda',
858
- 'UA' => 'Ukraine',
859
- 'AE' => 'United Arab Emirates',
860
- 'UY' => 'Uruguay',
861
- 'UM' => 'US Minor Outlying Islands',
862
- 'UZ' => 'Uzbekistan',
863
- 'VU' => 'Vanuatu',
864
- 'VE' => 'Venezuela',
865
- 'VN' => 'Vietnam',
866
- 'VG' => 'Virgin Islands (British)',
867
- 'VI' => 'Virgin Islands (USA)',
868
- 'WF' => 'Wallis and Futuna Islands',
869
- 'EH' => 'Western Sahara',
870
- 'WS' => 'Western Samoa',
871
- 'YE' => 'Yemen',
872
- 'ZM' => 'Zambia',
873
- 'ZW' => 'Zimbabwe',
874
- );
875
- }
876
- return $countries;
877
- }
878
-
879
- function monsterinsights_get_api_url(){
880
- return apply_filters( 'monsterinsights_get_api_url', 'api.monsterinsights.com/v2/' );
881
- }
882
-
883
- function monsterinsights_get_licensing_url(){
884
- return apply_filters( 'monsterinsights_get_licensing_url', 'https://www.monsterinsights.com' );
885
- }
886
-
887
- function monsterinsights_is_wp_seo_active( ) {
888
- $wp_seo_active = false; // @todo: improve this check. This is from old Yoast code.
889
-
890
- // Makes sure is_plugin_active is available when called from front end
891
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
892
- if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) || is_plugin_active( 'wordpress-seo-premium/wp-seo-premium.php' ) ) {
893
- $wp_seo_active = true;
894
- }
895
- return $wp_seo_active;
896
- }
897
-
898
- function monsterinsights_get_asset_version() {
899
- if ( monsterinsights_is_debug_mode() || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ) {
900
- return time();
901
- } else {
902
- return MONSTERINSIGHTS_VERSION;
903
- }
904
- }
905
-
906
- function monsterinsights_is_debug_mode() {
907
- $debug_mode = false;
908
- if ( defined( 'MONSTERINSIGHTS_DEBUG_MODE' ) && MONSTERINSIGHTS_DEBUG_MODE ) {
909
- $debug_mode = true;
910
- }
911
-
912
- return apply_filters( 'monsterinsights_is_debug_mode', $debug_mode );
913
- }
914
-
915
- function monsterinsights_is_network_active() {
916
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
917
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
918
- }
919
-
920
- if ( is_multisite() && is_plugin_active_for_network( plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ) ) ) {
921
- return true;
922
- } else {
923
- return false;
924
- }
925
- }
926
-
927
- if ( ! function_exists ( 'remove_class_filter' ) ) {
928
- /**
929
- * Remove Class Filter Without Access to Class Object
930
- *
931
- * In order to use the core WordPress remove_filter() on a filter added with the callback
932
- * to a class, you either have to have access to that class object, or it has to be a call
933
- * to a static method. This method allows you to remove filters with a callback to a class
934
- * you don't have access to.
935
- *
936
- * Works with WordPress 1.2 - 4.7+
937
- *
938
- * @param string $tag Filter to remove
939
- * @param string $class_name Class name for the filter's callback
940
- * @param string $method_name Method name for the filter's callback
941
- * @param int $priority Priority of the filter (default 10)
942
- *
943
- * @return bool Whether the function is removed.
944
- */
945
- function remove_class_filter( $tag, $class_name = '', $method_name = '', $priority = 10 ) {
946
- global $wp_filter;
947
- // Check that filter actually exists first
948
- if ( ! isset( $wp_filter[ $tag ] ) ) return FALSE;
949
- /**
950
- * If filter config is an object, means we're using WordPress 4.7+ and the config is no longer
951
- * a simple array, rather it is an object that implements the ArrayAccess interface.
952
- *
953
- * To be backwards compatible, we set $callbacks equal to the correct array as a reference (so $wp_filter is updated)
954
- *
955
- * @see https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/
956
- */
957
- if ( is_object( $wp_filter[ $tag ] ) && isset( $wp_filter[ $tag ]->callbacks ) ) {
958
- $callbacks = &$wp_filter[ $tag ]->callbacks;
959
- } else {
960
- $callbacks = &$wp_filter[ $tag ];
961
- }
962
- // Exit if there aren't any callbacks for specified priority
963
- if ( ! isset( $callbacks[ $priority ] ) || empty( $callbacks[ $priority ] ) ) return FALSE;
964
- // Loop through each filter for the specified priority, looking for our class & method
965
- foreach( (array) $callbacks[ $priority ] as $filter_id => $filter ) {
966
- // Filter should always be an array - array( $this, 'method' ), if not goto next
967
- if ( ! isset( $filter[ 'function' ] ) || ! is_array( $filter[ 'function' ] ) ) continue;
968
- // If first value in array is not an object, it can't be a class
969
- if ( ! is_object( $filter[ 'function' ][ 0 ] ) ) continue;
970
- // Method doesn't match the one we're looking for, goto next
971
- if ( $filter[ 'function' ][ 1 ] !== $method_name ) continue;
972
- // Method matched, now let's check the Class
973
- if ( get_class( $filter[ 'function' ][ 0 ] ) === $class_name ) {
974
- // Now let's remove it from the array
975
- unset( $callbacks[ $priority ][ $filter_id ] );
976
- // and if it was the only filter in that priority, unset that priority
977
- if ( empty( $callbacks[ $priority ] ) ) unset( $callbacks[ $priority ] );
978
- // and if the only filter for that tag, set the tag to an empty array
979
- if ( empty( $callbacks ) ) $callbacks = array();
980
- // If using WordPress older than 4.7
981
- if ( ! is_object( $wp_filter[ $tag ] ) ) {
982
- // Remove this filter from merged_filters, which specifies if filters have been sorted
983
- unset( $GLOBALS[ 'merged_filters' ][ $tag ] );
984
- }
985
- return TRUE;
986
- }
987
- }
988
- return FALSE;
989
- }
990
- } // End function exists
991
-
992
- if ( ! function_exists ( 'remove_class_action' ) ) {
993
- /**
994
- * Remove Class Action Without Access to Class Object
995
- *
996
- * In order to use the core WordPress remove_action() on an action added with the callback
997
- * to a class, you either have to have access to that class object, or it has to be a call
998
- * to a static method. This method allows you to remove actions with a callback to a class
999
- * you don't have access to.
1000
- *
1001
- * Works with WordPress 1.2 - 4.7+
1002
- *
1003
- * @param string $tag Action to remove
1004
- * @param string $class_name Class name for the action's callback
1005
- * @param string $method_name Method name for the action's callback
1006
- * @param int $priority Priority of the action (default 10)
1007
- *
1008
- * @return bool Whether the function is removed.
1009
- */
1010
- function remove_class_action( $tag, $class_name = '', $method_name = '', $priority = 10 ) {
1011
- remove_class_filter( $tag, $class_name, $method_name, $priority );
1012
- }
1013
- } // End function exists
1014
-
1015
- /**
1016
- * Format a big number, instead of 1000000 you get 1.0M, works with billions also.
1017
- *
1018
- * @param int $number
1019
- * @param int $precision
1020
- *
1021
- * @return string
1022
- */
1023
- function monsterinsights_round_number( $number, $precision = 2 ) {
1024
-
1025
- if ( $number < 1000000 ) {
1026
- // Anything less than a million
1027
- $number = number_format_i18n( $number );
1028
- } else if ( $number < 1000000000 ) {
1029
- // Anything less than a billion
1030
- $number = number_format_i18n( $number / 1000000, $precision ) . 'M';
1031
- } else {
1032
- // At least a billion
1033
- $number = number_format_i18n( $number / 1000000000, $precision ) . 'B';
1034
- }
1035
-
1036
- return $number;
1037
- }
1038
-
1039
- if ( ! function_exists( 'wp_get_jed_locale_data' ) ) {
1040
- /**
1041
- * Returns Jed-formatted localization data. Added for backwards-compatibility.
1042
- *
1043
- * @param string $domain Translation domain.
1044
- *
1045
- * @return array
1046
- */
1047
- function wp_get_jed_locale_data( $domain ) {
1048
- $translations = get_translations_for_domain( $domain );
1049
-
1050
- $locale = array(
1051
- '' => array(
1052
- 'domain' => $domain,
1053
- 'lang' => is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
1054
- ),
1055
- );
1056
-
1057
- if ( ! empty( $translations->headers['Plural-Forms'] ) ) {
1058
- $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
1059
- }
1060
-
1061
- foreach ( $translations->entries as $msgid => $entry ) {
1062
- $locale[ $msgid ] = $entry->translations;
1063
- }
1064
-
1065
- return $locale;
1066
- }
1067
- }
1068
-
1069
- function monsterinsights_get_inline_menu_icon() {
1070
- $scheme = get_user_option( 'admin_color', get_current_user_id() );
1071
- $use_dark_scheme = $scheme === 'light';
1072
- if ( $use_dark_scheme ) {
1073
- return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAFQUlEQVRYha2Yb2hXZRTHP+c3nc6pm07NF0KWWUtSo0wqzBdiZRItTKMaEZXSi0zRNAsqTBKKSFOa0B8Jigqz2lSwLMtqRURgRuCCLLNmselyZups2+/04pzbnt3de3eTDlzufc5znvN8n+ec55zzXFFV8pKITANOqmpTP3JTgIKq7sutPCJVzfUABeAb4DSwMENuKdABNObV3Wv8fwB0C6DAUX8/67sQ9Q8ANsVk5v5vgIDKWHsvcAgYCWzzCbc6kFJgh/PqgVHAb8DnWTpzA3LzHARmeXuqT/Zo0L/eeZuAV/x7fbRrwJPOu9Dbc4EDgJwNoMmurAt4Bljt7cmBjACvOl+BzTEdVzj/EWAj0O3tC84G0AIf3BRMeDz0GZcbBvzqKy+L9Q30A6AxXTdmARqQcPAAyv29CBjjO1RU1SKAiIwGFgLX+MrbgBnAh5ECVe0UkUMO6nHgFLA70J1McacD5gHbfTXzg77qwBeOBysPn830PnnVwXety7wL1AAV/ZoM+MIHdQCfAdfF+s8H/koBEz0rU9xgLtAInHG5j/KYrNWf8ap6OmFD7w+2/Cugwd/NmOkqgbIUS+wEdorIEOAwFqv6UBKgihQwANNc0b2quh1ARIZi/nUqZUycOrDDcCSps5AAaJBPkkStwNVAs4i8JiLHgBPASRFpFZEGEZktIpIBqBIoIWWH4nZegtl3fIofjAKeoyemfAe8hZnu64D/NjAsRcdEl1mcx6lvc+HLU6L3O97/JXBlgszF9KSVvXhswkxUC6wLdKzIA2iWC1+fMNlK72sASlMjrQHf4LIvAw8B7fScwmNAZ7DDs7MARSmjNsYf7oqak0wBjAXuBlb5Lo9wE0Yg6rHAOdjlR2KB9Qc384o0QOe4giUx/u3OX5oA5gEsCoexqBnYAxTTfMXHlvuOF4F5SYBKHPGaGH+jTzQxxefSnnVpYAIdg9x0PwEDkwSOAHUx3hafoDzGP5AB5gQ56h/XU+NjauJxCCxRjo7xOvw9ImKISBUwIWF8RLtVtT2jP6SdWBKe1QuQiCwDLsKcNKSoqJ8e8BJTREAHc4JBVTuBn4Gx/wISkflYndyNOXdI2/29OOAd7mfSIXkBOZUDxTACt2A78SLQnmDnBszOiwLeraT70Ld5/Mf1jPMxqyLGWqxcnYoFMqVvBTgOK9y7gOVAifMfdF4SqJk5Aa3FLFMNduxagQbvvJOUfIb51/f0lKSrsROyHCtlIyDtrrMJqOoHzAysRvrA28wmSBfAtd7uk6u8vwwr/JOqxm4sl01wvZ3AfhJyo+taAPyJhYi/gekCPIXdNitV9YyIXIIFqptVdVsf13MSkVJgJlZF4rvSqKq/BzJzgNexcPEp8LFPXAHcAFzqoKcAddjR5z2Cay/m4Arcl9cp+zFJFfA0dslMOwB1wD1AewGrTw4Ei2/zVcSP/lmRqrap6irs8gAwid7xDOAuzNwlgmXxF1T14ahXRPZjtU1k3+g5Tk8pkUUFzCwVWC003N/DgGVYIXheIF/EfmQcFczDW4DnsVtBCxbUtmIOPAAzY6MPLgMG+/dlDrIADHWlYL4QpZuZWLjYgp3SOb7QMbFFFLF6LDNB7sGcri7FP7qwWmcX9t8oSWaDA6zCqomXUuZ6U1UpYDXxH5jfgKWET/y7zXfolIgkJeJMEpES/xwMXKWq3aq6CLu9PAH8Eog/Fn2UYnlkDWa2c719E3Y/f8NX0AL8GHuianAXtuXx/lZ6brR9/npgcWgHcEfEkyg6ZqyyBrt1ptE+X9SkDJl6VX0/cyKnfwBb6gwNaZ8ExgAAAABJRU5ErkJggg';
1074
- } else {
1075
- return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AoEBjcfBsDvpwAABQBJREFUWMO1mGmollUQgJ9z79Vc01LLH0GLWRqlUhYV5o+LbRIVbVQSUSn9qJTKsqDCoqCINKUbtBEUFbbeDGyz1SIiaCHIINu18KZ1bbkuV+/Tj+arw8v7fvdVcuDjvGdmzsycM3Nm5nywE6BOVSfW4JukTmF3gtqifqJuVmc34ZunblFX7W6DzvYf2BDjPWpLRm9T7y/wzPw/DRhZmH+sfq/urb4YCp8JQwaqLwXuBXW0+pP6XjOZO+ueb9X2mE8OZTdl9MWBu199NL4XN05NvT1wh8R8prpGTbti0BEhbLt6t7ow5kdkPEl9zP/gkYKMowN/o7pU3RHzg3fFoHNj8epM4aY8ZoJvuPpj7HxwgTYgLoAFWac1091WgR8a4xxgH2Ah0JdS6gtlY4DZwAnADmAjMA14vSEgpdSrfg9sBm4BeoCVmex6gayepS6P3ZyT0SZksbDJcnikcPMmZN+zgud59Qx1RB2D3o9FW9R31ZMK9IPUP20O11XInqmuUrcG3xt1XNYVvwNSSptL+K/IjvxDoDPGteG6kcDgMkUppRXACnUIsA7YUNegERXGAEwNQZellJbHzodFfPXUjIwtwHDglzJiS4lBe4SSMugCjgfWqo+rvwF/AH+pXWqnOqOfXDMSaK06oaKf54Z/D6igj1bvzXLK5+rTYchHGf5ZdXiFjPHBc2Udg84P5qMqsvdzQf9APbaEZ2JWVj5u5KbIV7PURZmM+XUMag/mk0to1wWtUx3YT9lZErwPq9er3dkt/E3tzU54Rp2SMauA3zMErS1zhTpWvURdEKe8V7jQrOBOUwcF/97qbPWrcPP8KoP2DQFzC/gLAj+vZM1Vak8hF61V31L7msWKOjROvE89q4yhNSy+rYBfGorGV8RcFSyqESZ7hOu+UQeUMfyidhRwy0LB0AJ+TRNj/qjb/0QpUT2jpYS+ERhTkswA9sqEjALGNdGzMqXUXTNZrogi3F5sJ64GDgXGFhasjvGYDDe4HyXf1i3qKaVe4DtgbF6ZzwHuiZq0b2HN8hjzAF3Xj9IhO9mGDQX68gy8PpqoB9XuEj93hp/nZLjzmsTQZzvR9uwXaxY0EHdEuzo5EpklHeB+0bhvV69RWwN/beDKYHpNg+6I2z2hce261M4gXlRVz9RD1S+zlnRh3JBropVtQHfIXB3B38yYadEjvdZAzMjLhXpizI+tEDA4Gv+yrnFH1LJxIbdX/aKsNma9+++RIrapxyT1TmAeMDKltFU9HPgcODOl9GKTnQ0EpgMHBaobWJVS+jnjOQV4ItLFO8CbwDZgBHAqMAXoBSYBHcBm1JfzZ28EuOrl/9ODc5R6Vzwyq6BDvVTtbgHGA2sKiXFbydXfJUgpbUwpLQAateqwQj4DuDjSTWuKru+BlNIN2a6+ACYCv0dH2PhtCtfYjx0t4ZYR0a7uGeNw4GpgLnBgxt8HfAJsSOpWYD1wH7AqvocAz0Q2bgNGB62RoQfF95FhZAswLIQSZaBRbqYDPwHLogqcEhvdp7CJPqC9vwL5VtyUjor42B69zqvqXxU8S+IFOyq6iYcqdD3VONqngV8jbhol4e0sntqAnuIzumZAt8bnIOC4lNKOlNKceL3cCvyQsd/87/WNRuk29T51/5ifHu/zJ2MH69WvCz+zE+oroXdlL9pUkYdeUi/89xLU6VWAZn88fQoMjNtTBS+klF6pc6p/A2ye4OCYzm1lAAAAAElFTkSuQmCC';
1076
- }
1077
- }
1078
-
1079
-
1080
- function monsterinsights_get_shareasale_id() {
1081
- // Check if there's a constant.
1082
- $shareasale_id = '';
1083
- if ( defined( 'MONSTERINSIGHTS_SHAREASALE_ID' ) ) {
1084
- $shareasale_id = MONSTERINSIGHTS_SHAREASALE_ID;
1085
- }
1086
-
1087
- // If there's no constant, check if there's an option.
1088
- if ( empty( $shareasale_id ) ) {
1089
- $shareasale_id = get_option( 'monsterinsights_shareasale_id', '' );
1090
- }
1091
-
1092
- // Whether we have an ID or not, filter the ID.
1093
- $shareasale_id = apply_filters( 'monsterinsights_shareasale_id', $shareasale_id );
1094
-
1095
- // Ensure it's a number
1096
- $shareasale_id = absint( $shareasale_id );
1097
-
1098
- return $shareasale_id;
1099
- }
1100
-
1101
- // Passed in with mandatory default redirect and shareasaleid from monsterinsights_get_upgrade_link
1102
- function monsterinsights_get_shareasale_url( $shareasale_id, $shareasale_redirect ) {
1103
- // Check if there's a constant.
1104
- $custom = false;
1105
- if ( defined( 'MONSTERINSIGHTS_SHAREASALE_REDIRECT_URL' ) ) {
1106
- $shareasale_redirect = MONSTERINSIGHTS_SHAREASALE_REDIRECT_URL;
1107
- $custom = true;
1108
- }
1109
-
1110
- // If there's no constant, check if there's an option.
1111
- if ( empty( $custom ) ) {
1112
- $shareasale_redirect = get_option( 'monsterinsights_shareasale_redirect_url', '' );
1113
- $custom = true;
1114
- }
1115
-
1116
- // Whether we have an ID or not, filter the ID.
1117
- $shareasale_redirect = apply_filters( 'monsterinsights_shareasale_redirect_url', $shareasale_redirect, $custom );
1118
- $shareasale_url = sprintf( 'https://www.shareasale.com/r.cfm?B=971799&U=%s&M=69975&urllink=%s', $shareasale_id, $shareasale_redirect );
1119
-
1120
- return $shareasale_url;
1121
- }
1122
-
1123
- /**
1124
- * Get a clean page title for archives.
1125
- */
1126
- function monsterinsights_get_page_title() {
1127
-
1128
- $title = __( 'Archives' );
1129
-
1130
- if ( is_category() ) {
1131
- /* translators: Category archive title. %s: Category name */
1132
- $title = sprintf( __( 'Category: %s' ), single_cat_title( '', false ) );
1133
- } elseif ( is_tag() ) {
1134
- /* translators: Tag archive title. %s: Tag name */
1135
- $title = sprintf( __( 'Tag: %s' ), single_tag_title( '', false ) );
1136
- } elseif ( is_author() ) {
1137
- /* translators: Author archive title. %s: Author name */
1138
- $title = sprintf( __( 'Author: %s' ), '<span class="vcard">' . get_the_author() . '</span>' );
1139
- } elseif ( is_year() ) {
1140
- /* translators: Yearly archive title. %s: Year */
1141
- $title = sprintf( __( 'Year: %s' ), get_the_date( _x( 'Y', 'yearly archives date format' ) ) );
1142
- } elseif ( is_month() ) {
1143
- /* translators: Monthly archive title. %s: Month name and year */
1144
- $title = sprintf( __( 'Month: %s' ), get_the_date( _x( 'F Y', 'monthly archives date format' ) ) );
1145
- } elseif ( is_day() ) {
1146
- /* translators: Daily archive title. %s: Date */
1147
- $title = sprintf( __( 'Day: %s' ), get_the_date( _x( 'F j, Y', 'daily archives date format' ) ) );
1148
- } elseif ( is_tax( 'post_format' ) ) {
1149
- if ( is_tax( 'post_format', 'post-format-aside' ) ) {
1150
- $title = _x( 'Asides', 'post format archive title' );
1151
- } elseif ( is_tax( 'post_format', 'post-format-gallery' ) ) {
1152
- $title = _x( 'Galleries', 'post format archive title' );
1153
- } elseif ( is_tax( 'post_format', 'post-format-image' ) ) {
1154
- $title = _x( 'Images', 'post format archive title' );
1155
- } elseif ( is_tax( 'post_format', 'post-format-video' ) ) {
1156
- $title = _x( 'Videos', 'post format archive title' );
1157
- } elseif ( is_tax( 'post_format', 'post-format-quote' ) ) {
1158
- $title = _x( 'Quotes', 'post format archive title' );
1159
- } elseif ( is_tax( 'post_format', 'post-format-link' ) ) {
1160
- $title = _x( 'Links', 'post format archive title' );
1161
- } elseif ( is_tax( 'post_format', 'post-format-status' ) ) {
1162
- $title = _x( 'Statuses', 'post format archive title' );
1163
- } elseif ( is_tax( 'post_format', 'post-format-audio' ) ) {
1164
- $title = _x( 'Audio', 'post format archive title' );
1165
- } elseif ( is_tax( 'post_format', 'post-format-chat' ) ) {
1166
- $title = _x( 'Chats', 'post format archive title' );
1167
- }
1168
- } elseif ( is_post_type_archive() ) {
1169
- /* translators: Post type archive title. %s: Post type name */
1170
- $title = sprintf( __( 'Archives: %s' ), post_type_archive_title( '', false ) );
1171
- } elseif ( is_tax() ) {
1172
- $tax = get_taxonomy( get_queried_object()->taxonomy );
1173
- /* translators: Taxonomy term archive title. 1: Taxonomy singular name, 2: Current taxonomy term */
1174
- $title = sprintf( __( '%1$s: %2$s' ), $tax->labels->singular_name, single_term_title( '', false ) );
1175
- }
1176
-
1177
- return $title;
1178
-
1179
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Helper functions.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Helper
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ function monsterinsights_is_page_reload() {
18
+ // Can't be a refresh without having a referrer
19
+ if ( ! isset( $_SERVER['HTTP_REFERER'] ) ) {
20
+ return false;
21
+ }
22
+
23
+ // IF the referrer is identical to the current page request, then it's a refresh
24
+ return ( parse_url( $_SERVER['HTTP_REFERER'], PHP_URL_PATH ) === parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ) );
25
+ }
26
+
27
+
28
+ function monsterinsights_track_user( $user_id = -1 ) {
29
+ if ( $user_id === -1 ) {
30
+ $user = wp_get_current_user();
31
+ } else {
32
+ $user = new WP_User( $user_id );
33
+ }
34
+
35
+ $track_user = true;
36
+ $roles = monsterinsights_get_option( 'ignore_users', array() );
37
+
38
+ if ( ! empty( $roles ) && is_array( $roles ) ) {
39
+ foreach ( $roles as $role ) {
40
+ if ( is_string( $role ) ) {
41
+ if ( user_can( $user, $role ) ) {
42
+ $track_user = false;
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ $track_super_admin = apply_filters( 'monsterinsights_track_super_admins', false );
50
+ if ( $track_super_admin === false && is_multisite() && is_super_admin() ) {
51
+ $track_user = false;
52
+ }
53
+
54
+ // or if UA code is not entered
55
+ $ua_code = monsterinsights_get_ua();
56
+ if ( empty( $ua_code ) ) {
57
+ $track_user = false;
58
+ }
59
+
60
+ return apply_filters( 'monsterinsights_track_user', $track_user, $user );
61
+ }
62
+
63
+ function monsterinsights_get_client_id( $payment_id = false ) {
64
+ if ( is_object( $payment_id ) ) {
65
+ $payment_id = $payment_id->ID;
66
+ }
67
+ $user_cid = monsterinsights_get_uuid();
68
+ $saved_cid = ! empty( $payment_id ) ? get_post_meta( $payment_id, '_yoast_gau_uuid', true ) : false;
69
+
70
+ if ( ! empty( $payment_id ) && ! empty( $saved_cid ) ) {
71
+ return $saved_cid;
72
+ } else if ( ! empty( $user_cid ) ) {
73
+ return $user_cid;
74
+ } else {
75
+ return monsterinsights_generate_uuid();
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Returns the Google Analytics clientId to store for later use
81
+ *
82
+ * @since 6.0.0
83
+ *
84
+ * @link https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#getClientId
85
+ *
86
+ * @return bool|string False if cookie isn't set, GA UUID otherwise
87
+ */
88
+ function monsterinsights_get_uuid() {
89
+ if ( empty( $_COOKIE['_ga'] ) ) {
90
+ return false;
91
+ }
92
+
93
+ /**
94
+ * Example cookie formats:
95
+ *
96
+ * GA1.2.XXXXXXX.YYYYY
97
+ * _ga=1.2.XXXXXXX.YYYYYY -- We want the XXXXXXX.YYYYYY part
98
+ *
99
+ */
100
+
101
+ $ga_cookie = $_COOKIE['_ga'];
102
+ $cookie_parts = explode('.', $ga_cookie );
103
+ if ( is_array( $cookie_parts ) && ! empty( $cookie_parts[2] ) && ! empty( $cookie_parts[3] ) ) {
104
+ $uuid = (string) $cookie_parts[2] . '.' . (string) $cookie_parts[3];
105
+ if ( is_string( $uuid ) ) {
106
+ return $uuid;
107
+ } else {
108
+ return false;
109
+ }
110
+ } else {
111
+ return false;
112
+ }
113
+ }
114
+
115
+
116
+ /**
117
+ * Generate UUID v4 function - needed to generate a CID when one isn't available
118
+ *
119
+ * @link http://www.stumiller.me/implementing-google-analytics-measurement-protocol-in-php-and-wordpress/
120
+ *
121
+ * @since 6.1.8
122
+ * @return string
123
+ */
124
+ function monsterinsights_generate_uuid() {
125
+
126
+ return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
127
+
128
+ // 32 bits for "time_low"
129
+ mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
130
+
131
+ // 16 bits for "time_mid"
132
+ mt_rand( 0, 0xffff ),
133
+
134
+ // 16 bits for "time_hi_and_version",
135
+ // four most significant bits holds version number 4
136
+ mt_rand( 0, 0x0fff ) | 0x4000,
137
+
138
+ // 16 bits, 8 bits for "clk_seq_hi_res",
139
+ // 8 bits for "clk_seq_low",
140
+ // two most significant bits holds zero and one for variant DCE1.1
141
+ mt_rand( 0, 0x3fff ) | 0x8000,
142
+
143
+ // 48 bits for "node"
144
+ mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
145
+ );
146
+ }
147
+
148
+ /**
149
+ * Returns the Google Analytics clientId to store for later use
150
+ *
151
+ * @since 6.0.0
152
+ *
153
+ * @return GA UUID or error code.
154
+ */
155
+ function monsterinsights_get_cookie( $debug = false ) {
156
+ if ( empty( $_COOKIE['_ga'] ) ) {
157
+ return ( $debug ) ? 'FCE' : false;
158
+ }
159
+
160
+ $ga_cookie = $_COOKIE['_ga'];
161
+ $cookie_parts = explode('.', $ga_cookie );
162
+ if ( is_array( $cookie_parts ) && ! empty( $cookie_parts[2] ) && ! empty( $cookie_parts[3] ) ) {
163
+ $uuid = (string) $cookie_parts[2] . '.' . (string) $cookie_parts[3];
164
+ if ( is_string( $uuid ) ) {
165
+ return $ga_cookie;
166
+ } else {
167
+ return ( $debug ) ? 'FA' : false;
168
+ }
169
+ } else {
170
+ return ( $debug ) ? 'FAE' : false;
171
+ }
172
+ }
173
+
174
+
175
+ function monsterinsights_generate_ga_client_id() {
176
+ return rand(100000000,999999999) . '.' . time();
177
+ }
178
+
179
+
180
+ /**
181
+ * Hours between two timestamps.
182
+ *
183
+ * @access public
184
+ * @since 6.0.0
185
+ *
186
+ * @param string $start Timestamp of start time (in seconds since Unix).
187
+ * @param string $stop Timestamp of stop time (in seconds since Unix). Optional. If not used, current_time (in UTC 0 / GMT ) is used.
188
+ *
189
+ * @return int Hours between the two timestamps, rounded.
190
+ */
191
+ function monsterinsights_hours_between( $start, $stop = false ) {
192
+ if ( $stop === false ) {
193
+ $stop = time();
194
+ }
195
+
196
+ $diff = (int) abs( $stop - $start );
197
+ $hours = round( $diff / HOUR_IN_SECONDS );
198
+ return $hours;
199
+ }
200
+
201
+ /**
202
+ * Is This MonsterInsights Pro?
203
+ *
204
+ * We use this function monsterinsights_to determine if the install is a pro version or a lite version install of MonsterInsights.
205
+ * If the install is a lite version we disable the install from admin functionality[1] for addons as WordPress.org requires us to,
206
+ * we change the links for where to get support (wp.org forum for free; our site for pro), we use this determine what class to load as
207
+ * the base class in addons (to avoid fatal errors) and we use this on the system info page to know what constants to display values for
208
+ * as the lite and pro versions of our plugin have different constants (and names for those constants) you can declare and use.
209
+ *
210
+ * [1] Note: This is not "feature-locking" under GPL guidelines but rather something WordPress.org requires us to do to stay
211
+ * in compliance with their rules. We wish we didn't have to do this, as in our oppinion this diminishes the user experience
212
+ * of users installing our free and premium addons, and we'd love to turn this on for non-Pro installs, but we're not allowed to.
213
+ * If WordPress.org ever changes their mind on this subject, we'd totally turn on that feature for Lite installs in a heartbeat.
214
+ *
215
+ * @todo Are we allowed to turn on admin installing if the user has to manually declare a PHP constant (and thus would not be on
216
+ * either by default or via any sort of user interface)? If so, we could add a constant for forcing Pro version so that users can see
217
+ * for themselves that we're not feature locking anything inside the plugin + it would make it easier for our team to test stuff (both via
218
+ * Travis-CI but also when installing addons to test with the Lite version). Also this would allow for a better user experience for users
219
+ * who want that feature.
220
+ *
221
+ * @since 6.0.0
222
+ * @access public
223
+ *
224
+ * @return bool True if pro version.
225
+ */
226
+ function monsterinsights_is_pro_version() {
227
+ if ( class_exists( 'MonsterInsights' ) ) {
228
+ return true;
229
+ } else {
230
+ return false;
231
+ }
232
+ }
233
+
234
+
235
+ /**
236
+ * Get the user roles of this WordPress blog
237
+ *
238
+ * @return array
239
+ */
240
+ function monsterinsights_get_roles() {
241
+ global $wp_roles;
242
+
243
+ $all_roles = $wp_roles->roles;
244
+ $roles = array();
245
+
246
+ /**
247
+ * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
248
+ *
249
+ * @api array $all_roles
250
+ */
251
+ $editable_roles = apply_filters( 'editable_roles', $all_roles );
252
+
253
+ foreach ( $editable_roles as $id => $name ) {
254
+ $roles[ $id ] = translate_user_role( $name['name'] );
255
+ }
256
+
257
+ return $roles;
258
+ }
259
+
260
+ /**
261
+ * Get the user roles which can manage options. Used to prevent these roles from getting unselected in the settings.
262
+ *
263
+ * @return array
264
+ */
265
+ function monsterinsights_get_manage_options_roles() {
266
+ global $wp_roles;
267
+
268
+ $all_roles = $wp_roles->roles;
269
+ $roles = array();
270
+
271
+ /**
272
+ * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
273
+ *
274
+ * @api array $all_roles
275
+ */
276
+ $editable_roles = apply_filters( 'editable_roles', $all_roles );
277
+
278
+ foreach ( $editable_roles as $id => $role ) {
279
+ if ( isset( $role['capabilities']['manage_options'] ) && $role['capabilities']['manage_options'] ) {
280
+ $roles[ $id ] = translate_user_role( $role['name'] );
281
+ }
282
+ }
283
+
284
+ return $roles;
285
+ }
286
+
287
+ /** Need to escape in advance of passing in $text. */
288
+ function monsterinsights_get_message( $type = 'error', $text = '' ) {
289
+ $div = '';
290
+ if ( $type === 'error' || $type === 'alert' || $type === 'success' || $type === 'info' ) {
291
+ $base = MonsterInsights();
292
+ return $base->notices->display_inline_notice( 'monsterinsights_standard_notice', '', $text, $type, false, array( 'skip_message_escape' => true ) );
293
+ } else {
294
+ return '';
295
+ }
296
+ }
297
+
298
+ function monsterinsights_is_dev_url( $url = '' ) {
299
+ $is_local_url = false;
300
+ // Trim it up
301
+ $url = strtolower( trim( $url ) );
302
+ // Need to get the host...so let's add the scheme so we can use parse_url
303
+ if ( false === strpos( $url, 'http://' ) && false === strpos( $url, 'https://' ) ) {
304
+ $url = 'http://' . $url;
305
+ }
306
+ $url_parts = parse_url( $url );
307
+ $host = ! empty( $url_parts['host'] ) ? $url_parts['host'] : false;
308
+ if ( ! empty( $url ) && ! empty( $host ) ) {
309
+ if ( false !== ip2long( $host ) ) {
310
+ if ( ! filter_var( $host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
311
+ $is_local_url = true;
312
+ }
313
+ } else if ( 'localhost' === $host ) {
314
+ $is_local_url = true;
315
+ }
316
+
317
+ $tlds_to_check = array( '.local', ':8888', ':8080', ':8081', '.invalid', '.example', '.test' );
318
+ foreach ( $tlds_to_check as $tld ) {
319
+ if ( false !== strpos( $host, $tld ) ) {
320
+ $is_local_url = true;
321
+ break;
322
+ }
323
+
324
+ }
325
+ if ( substr_count( $host, '.' ) > 1 ) {
326
+ $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
327
+ foreach ( $subdomains_to_check as $subdomain ) {
328
+ $subdomain = str_replace( '.', '(.)', $subdomain );
329
+ $subdomain = str_replace( array( '*', '(.)' ), '(.*)', $subdomain );
330
+ if ( preg_match( '/^(' . $subdomain . ')/', $host ) ) {
331
+ $is_local_url = true;
332
+ break;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ return $is_local_url;
338
+ }
339
+
340
+ // Set cookie to expire in 2 years
341
+ function monsterinsights_get_cookie_expiration_date( $time ) {
342
+ return date('D, j F Y H:i:s', time() + $time );
343
+ }
344
+
345
+ function monsterinsights_string_ends_with( $string, $ending ) {
346
+ $strlen = strlen($string);
347
+ $endinglen = strlen($ending);
348
+ if ( $endinglen > $strlen ) {
349
+ return false;
350
+ }
351
+ return substr_compare( $string, $ending, $strlen - $endinglen, $endinglen) === 0;
352
+ }
353
+
354
+ function monsterinsights_string_starts_with( $string, $start ) {
355
+ if ( ! is_string( $string ) || ! is_string( $start ) ) {
356
+ return false;
357
+ }
358
+
359
+ return substr( $string, 0, strlen( $start ) ) === $start;
360
+ }
361
+
362
+ function monsterinsights_get_country_list( $translated = false ) {
363
+ if ( $translated ) {
364
+ $countries = array(
365
+ '' => '',
366
+ 'US' => __( 'United States', 'google-analytics-for-wordpress' ),
367
+ 'CA' => __( 'Canada', 'google-analytics-for-wordpress' ),
368
+ 'GB' => __( 'United Kingdom', 'google-analytics-for-wordpress' ),
369
+ 'AF' => __( 'Afghanistan', 'google-analytics-for-wordpress' ),
370
+ 'AX' => __( '&#197;land Islands', 'google-analytics-for-wordpress' ),
371
+ 'AL' => __( 'Albania', 'google-analytics-for-wordpress' ),
372
+ 'DZ' => __( 'Algeria', 'google-analytics-for-wordpress' ),
373
+ 'AS' => __( 'American Samoa', 'google-analytics-for-wordpress' ),
374
+ 'AD' => __( 'Andorra', 'google-analytics-for-wordpress' ),
375
+ 'AO' => __( 'Angola', 'google-analytics-for-wordpress' ),
376
+ 'AI' => __( 'Anguilla', 'google-analytics-for-wordpress' ),
377
+ 'AQ' => __( 'Antarctica', 'google-analytics-for-wordpress' ),
378
+ 'AG' => __( 'Antigua and Barbuda', 'google-analytics-for-wordpress' ),
379
+ 'AR' => __( 'Argentina', 'google-analytics-for-wordpress' ),
380
+ 'AM' => __( 'Armenia', 'google-analytics-for-wordpress' ),
381
+ 'AW' => __( 'Aruba', 'google-analytics-for-wordpress' ),
382
+ 'AU' => __( 'Australia', 'google-analytics-for-wordpress' ),
383
+ 'AT' => __( 'Austria', 'google-analytics-for-wordpress' ),
384
+ 'AZ' => __( 'Azerbaijan', 'google-analytics-for-wordpress' ),
385
+ 'BS' => __( 'Bahamas', 'google-analytics-for-wordpress' ),
386
+ 'BH' => __( 'Bahrain', 'google-analytics-for-wordpress' ),
387
+ 'BD' => __( 'Bangladesh', 'google-analytics-for-wordpress' ),
388
+ 'BB' => __( 'Barbados', 'google-analytics-for-wordpress' ),
389
+ 'BY' => __( 'Belarus', 'google-analytics-for-wordpress' ),
390
+ 'BE' => __( 'Belgium', 'google-analytics-for-wordpress' ),
391
+ 'BZ' => __( 'Belize', 'google-analytics-for-wordpress' ),
392
+ 'BJ' => __( 'Benin', 'google-analytics-for-wordpress' ),
393
+ 'BM' => __( 'Bermuda', 'google-analytics-for-wordpress' ),
394
+ 'BT' => __( 'Bhutan', 'google-analytics-for-wordpress' ),
395
+ 'BO' => __( 'Bolivia', 'google-analytics-for-wordpress' ),
396
+ 'BQ' => __( 'Bonaire, Saint Eustatius and Saba', 'google-analytics-for-wordpress' ),
397
+ 'BA' => __( 'Bosnia and Herzegovina', 'google-analytics-for-wordpress' ),
398
+ 'BW' => __( 'Botswana', 'google-analytics-for-wordpress' ),
399
+ 'BV' => __( 'Bouvet Island', 'google-analytics-for-wordpress' ),
400
+ 'BR' => __( 'Brazil', 'google-analytics-for-wordpress' ),
401
+ 'IO' => __( 'British Indian Ocean Territory', 'google-analytics-for-wordpress' ),
402
+ 'BN' => __( 'Brunei Darrussalam', 'google-analytics-for-wordpress' ),
403
+ 'BG' => __( 'Bulgaria', 'google-analytics-for-wordpress' ),
404
+ 'BF' => __( 'Burkina Faso', 'google-analytics-for-wordpress' ),
405
+ 'BI' => __( 'Burundi', 'google-analytics-for-wordpress' ),
406
+ 'KH' => __( 'Cambodia', 'google-analytics-for-wordpress' ),
407
+ 'CM' => __( 'Cameroon', 'google-analytics-for-wordpress' ),
408
+ 'CV' => __( 'Cape Verde', 'google-analytics-for-wordpress' ),
409
+ 'KY' => __( 'Cayman Islands', 'google-analytics-for-wordpress' ),
410
+ 'CF' => __( 'Central African Republic', 'google-analytics-for-wordpress' ),
411
+ 'TD' => __( 'Chad', 'google-analytics-for-wordpress' ),
412
+ 'CL' => __( 'Chile', 'google-analytics-for-wordpress' ),
413
+ 'CN' => __( 'China', 'google-analytics-for-wordpress' ),
414
+ 'CX' => __( 'Christmas Island', 'google-analytics-for-wordpress' ),
415
+ 'CC' => __( 'Cocos Islands', 'google-analytics-for-wordpress' ),
416
+ 'CO' => __( 'Colombia', 'google-analytics-for-wordpress' ),
417
+ 'KM' => __( 'Comoros', 'google-analytics-for-wordpress' ),
418
+ 'CD' => __( 'Congo, Democratic People\'s Republic', 'google-analytics-for-wordpress' ),
419
+ 'CG' => __( 'Congo, Republic of', 'google-analytics-for-wordpress' ),
420
+ 'CK' => __( 'Cook Islands', 'google-analytics-for-wordpress' ),
421
+ 'CR' => __( 'Costa Rica', 'google-analytics-for-wordpress' ),
422
+ 'CI' => __( 'Cote d\'Ivoire', 'google-analytics-for-wordpress' ),
423
+ 'HR' => __( 'Croatia/Hrvatska', 'google-analytics-for-wordpress' ),
424
+ 'CU' => __( 'Cuba', 'google-analytics-for-wordpress' ),
425
+ 'CW' => __( 'Cura&Ccedil;ao', 'google-analytics-for-wordpress' ),
426
+ 'CY' => __( 'Cyprus', 'google-analytics-for-wordpress' ),
427
+ 'CZ' => __( 'Czechia', 'google-analytics-for-wordpress' ),
428
+ 'DK' => __( 'Denmark', 'google-analytics-for-wordpress' ),
429
+ 'DJ' => __( 'Djibouti', 'google-analytics-for-wordpress' ),
430
+ 'DM' => __( 'Dominica', 'google-analytics-for-wordpress' ),
431
+ 'DO' => __( 'Dominican Republic', 'google-analytics-for-wordpress' ),
432
+ 'TP' => __( 'East Timor', 'google-analytics-for-wordpress' ),
433
+ 'EC' => __( 'Ecuador', 'google-analytics-for-wordpress' ),
434
+ 'EG' => __( 'Egypt', 'google-analytics-for-wordpress' ),
435
+ 'GQ' => __( 'Equatorial Guinea', 'google-analytics-for-wordpress' ),
436
+ 'SV' => __( 'El Salvador', 'google-analytics-for-wordpress' ),
437
+ 'ER' => __( 'Eritrea', 'google-analytics-for-wordpress' ),
438
+ 'EE' => __( 'Estonia', 'google-analytics-for-wordpress' ),
439
+ 'ET' => __( 'Ethiopia', 'google-analytics-for-wordpress' ),
440
+ 'FK' => __( 'Falkland Islands', 'google-analytics-for-wordpress' ),
441
+ 'FO' => __( 'Faroe Islands', 'google-analytics-for-wordpress' ),
442
+ 'FJ' => __( 'Fiji', 'google-analytics-for-wordpress' ),
443
+ 'FI' => __( 'Finland', 'google-analytics-for-wordpress' ),
444
+ 'FR' => __( 'France', 'google-analytics-for-wordpress' ),
445
+ 'GF' => __( 'French Guiana', 'google-analytics-for-wordpress' ),
446
+ 'PF' => __( 'French Polynesia', 'google-analytics-for-wordpress' ),
447
+ 'TF' => __( 'French Southern Territories', 'google-analytics-for-wordpress' ),
448
+ 'GA' => __( 'Gabon', 'google-analytics-for-wordpress' ),
449
+ 'GM' => __( 'Gambia', 'google-analytics-for-wordpress' ),
450
+ 'GE' => __( 'Georgia', 'google-analytics-for-wordpress' ),
451
+ 'DE' => __( 'Germany', 'google-analytics-for-wordpress' ),
452
+ 'GR' => __( 'Greece', 'google-analytics-for-wordpress' ),
453
+ 'GH' => __( 'Ghana', 'google-analytics-for-wordpress' ),
454
+ 'GI' => __( 'Gibraltar', 'google-analytics-for-wordpress' ),
455
+ 'GL' => __( 'Greenland', 'google-analytics-for-wordpress' ),
456
+ 'GD' => __( 'Grenada', 'google-analytics-for-wordpress' ),
457
+ 'GP' => __( 'Guadeloupe', 'google-analytics-for-wordpress' ),
458
+ 'GU' => __( 'Guam', 'google-analytics-for-wordpress' ),
459
+ 'GT' => __( 'Guatemala', 'google-analytics-for-wordpress' ),
460
+ 'GG' => __( 'Guernsey', 'google-analytics-for-wordpress' ),
461
+ 'GN' => __( 'Guinea', 'google-analytics-for-wordpress' ),
462
+ 'GW' => __( 'Guinea-Bissau', 'google-analytics-for-wordpress' ),
463
+ 'GY' => __( 'Guyana', 'google-analytics-for-wordpress' ),
464
+ 'HT' => __( 'Haiti', 'google-analytics-for-wordpress' ),
465
+ 'HM' => __( 'Heard and McDonald Islands', 'google-analytics-for-wordpress' ),
466
+ 'VA' => __( 'Holy See (City Vatican State)', 'google-analytics-for-wordpress' ),
467
+ 'HN' => __( 'Honduras', 'google-analytics-for-wordpress' ),
468
+ 'HK' => __( 'Hong Kong', 'google-analytics-for-wordpress' ),
469
+ 'HU' => __( 'Hungary', 'google-analytics-for-wordpress' ),
470
+ 'IS' => __( 'Iceland', 'google-analytics-for-wordpress' ),
471
+ 'IN' => __( 'India', 'google-analytics-for-wordpress' ),
472
+ 'ID' => __( 'Indonesia', 'google-analytics-for-wordpress' ),
473
+ 'IR' => __( 'Iran', 'google-analytics-for-wordpress' ),
474
+ 'IQ' => __( 'Iraq', 'google-analytics-for-wordpress' ),
475
+ 'IE' => __( 'Ireland', 'google-analytics-for-wordpress' ),
476
+ 'IM' => __( 'Isle of Man', 'google-analytics-for-wordpress' ),
477
+ 'IL' => __( 'Israel', 'google-analytics-for-wordpress' ),
478
+ 'IT' => __( 'Italy', 'google-analytics-for-wordpress' ),
479
+ 'JM' => __( 'Jamaica', 'google-analytics-for-wordpress' ),
480
+ 'JP' => __( 'Japan', 'google-analytics-for-wordpress' ),
481
+ 'JE' => __( 'Jersey', 'google-analytics-for-wordpress' ),
482
+ 'JO' => __( 'Jordan', 'google-analytics-for-wordpress' ),
483
+ 'KZ' => __( 'Kazakhstan', 'google-analytics-for-wordpress' ),
484
+ 'KE' => __( 'Kenya', 'google-analytics-for-wordpress' ),
485
+ 'KI' => __( 'Kiribati', 'google-analytics-for-wordpress' ),
486
+ 'KW' => __( 'Kuwait', 'google-analytics-for-wordpress' ),
487
+ 'KG' => __( 'Kyrgyzstan', 'google-analytics-for-wordpress' ),
488
+ 'LA' => __( 'Lao People\'s Democratic Republic', 'google-analytics-for-wordpress' ),
489
+ 'LV' => __( 'Latvia', 'google-analytics-for-wordpress' ),
490
+ 'LB' => __( 'Lebanon', 'google-analytics-for-wordpress' ),
491
+ 'LS' => __( 'Lesotho', 'google-analytics-for-wordpress' ),
492
+ 'LR' => __( 'Liberia', 'google-analytics-for-wordpress' ),
493
+ 'LY' => __( 'Libyan Arab Jamahiriya', 'google-analytics-for-wordpress' ),
494
+ 'LI' => __( 'Liechtenstein', 'google-analytics-for-wordpress' ),
495
+ 'LT' => __( 'Lithuania', 'google-analytics-for-wordpress' ),
496
+ 'LU' => __( 'Luxembourg', 'google-analytics-for-wordpress' ),
497
+ 'MO' => __( 'Macau', 'google-analytics-for-wordpress' ),
498
+ 'MK' => __( 'Macedonia (FYROM)', 'google-analytics-for-wordpress' ),
499
+ 'MG' => __( 'Madagascar', 'google-analytics-for-wordpress' ),
500
+ 'MW' => __( 'Malawi', 'google-analytics-for-wordpress' ),
501
+ 'MY' => __( 'Malaysia', 'google-analytics-for-wordpress' ),
502
+ 'MV' => __( 'Maldives', 'google-analytics-for-wordpress' ),
503
+ 'ML' => __( 'Mali', 'google-analytics-for-wordpress' ),
504
+ 'MT' => __( 'Malta', 'google-analytics-for-wordpress' ),
505
+ 'MH' => __( 'Marshall Islands', 'google-analytics-for-wordpress' ),
506
+ 'MQ' => __( 'Martinique', 'google-analytics-for-wordpress' ),
507
+ 'MR' => __( 'Mauritania', 'google-analytics-for-wordpress' ),
508
+ 'MU' => __( 'Mauritius', 'google-analytics-for-wordpress' ),
509
+ 'YT' => __( 'Mayotte', 'google-analytics-for-wordpress' ),
510
+ 'MX' => __( 'Mexico', 'google-analytics-for-wordpress' ),
511
+ 'FM' => __( 'Micronesia', 'google-analytics-for-wordpress' ),
512
+ 'MD' => __( 'Moldova, Republic of', 'google-analytics-for-wordpress' ),
513
+ 'MC' => __( 'Monaco', 'google-analytics-for-wordpress' ),
514
+ 'MN' => __( 'Mongolia', 'google-analytics-for-wordpress' ),
515
+ 'ME' => __( 'Montenegro', 'google-analytics-for-wordpress' ),
516
+ 'MS' => __( 'Montserrat', 'google-analytics-for-wordpress' ),
517
+ 'MA' => __( 'Morocco', 'google-analytics-for-wordpress' ),
518
+ 'MZ' => __( 'Mozambique', 'google-analytics-for-wordpress' ),
519
+ 'MM' => __( 'Myanmar', 'google-analytics-for-wordpress' ),
520
+ 'NA' => __( 'Namibia', 'google-analytics-for-wordpress' ),
521
+ 'NR' => __( 'Nauru', 'google-analytics-for-wordpress' ),
522
+ 'NP' => __( 'Nepal', 'google-analytics-for-wordpress' ),
523
+ 'NL' => __( 'Netherlands', 'google-analytics-for-wordpress' ),
524
+ 'AN' => __( 'Netherlands Antilles', 'google-analytics-for-wordpress' ),
525
+ 'NC' => __( 'New Caledonia', 'google-analytics-for-wordpress' ),
526
+ 'NZ' => __( 'New Zealand', 'google-analytics-for-wordpress' ),
527
+ 'NI' => __( 'Nicaragua', 'google-analytics-for-wordpress' ),
528
+ 'NE' => __( 'Niger', 'google-analytics-for-wordpress' ),
529
+ 'NG' => __( 'Nigeria', 'google-analytics-for-wordpress' ),
530
+ 'NU' => __( 'Niue', 'google-analytics-for-wordpress' ),
531
+ 'NF' => __( 'Norfolk Island', 'google-analytics-for-wordpress' ),
532
+ 'KP' => __( 'North Korea', 'google-analytics-for-wordpress' ),
533
+ 'MP' => __( 'Northern Mariana Islands', 'google-analytics-for-wordpress' ),
534
+ 'NO' => __( 'Norway', 'google-analytics-for-wordpress' ),
535
+ 'OM' => __( 'Oman', 'google-analytics-for-wordpress' ),
536
+ 'PK' => __( 'Pakistan', 'google-analytics-for-wordpress' ),
537
+ 'PW' => __( 'Palau', 'google-analytics-for-wordpress' ),
538
+ 'PS' => __( 'Palestinian Territories', 'google-analytics-for-wordpress' ),
539
+ 'PA' => __( 'Panama', 'google-analytics-for-wordpress' ),
540
+ 'PG' => __( 'Papua New Guinea', 'google-analytics-for-wordpress' ),
541
+ 'PY' => __( 'Paraguay', 'google-analytics-for-wordpress' ),
542
+ 'PE' => __( 'Peru', 'google-analytics-for-wordpress' ),
543
+ 'PH' => __( 'Philippines', 'google-analytics-for-wordpress' ),
544
+ 'PN' => __( 'Pitcairn Island', 'google-analytics-for-wordpress' ),
545
+ 'PL' => __( 'Poland', 'google-analytics-for-wordpress' ),
546
+ 'PT' => __( 'Portugal', 'google-analytics-for-wordpress' ),
547
+ 'PR' => __( 'Puerto Rico', 'google-analytics-for-wordpress' ),
548
+ 'QA' => __( 'Qatar', 'google-analytics-for-wordpress' ),
549
+ 'XK' => __( 'Republic of Kosovo', 'google-analytics-for-wordpress' ),
550
+ 'RE' => __( 'Reunion Island', 'google-analytics-for-wordpress' ),
551
+ 'RO' => __( 'Romania', 'google-analytics-for-wordpress' ),
552
+ 'RU' => __( 'Russian Federation', 'google-analytics-for-wordpress' ),
553
+ 'RW' => __( 'Rwanda', 'google-analytics-for-wordpress' ),
554
+ 'BL' => __( 'Saint Barth&eacute;lemy', 'google-analytics-for-wordpress' ),
555
+ 'SH' => __( 'Saint Helena', 'google-analytics-for-wordpress' ),
556
+ 'KN' => __( 'Saint Kitts and Nevis', 'google-analytics-for-wordpress' ),
557
+ 'LC' => __( 'Saint Lucia', 'google-analytics-for-wordpress' ),
558
+ 'MF' => __( 'Saint Martin (French)', 'google-analytics-for-wordpress' ),
559
+ 'SX' => __( 'Saint Martin (Dutch)', 'google-analytics-for-wordpress' ),
560
+ 'PM' => __( 'Saint Pierre and Miquelon', 'google-analytics-for-wordpress' ),
561
+ 'VC' => __( 'Saint Vincent and the Grenadines', 'google-analytics-for-wordpress' ),
562
+ 'SM' => __( 'San Marino', 'google-analytics-for-wordpress' ),
563
+ 'ST' => __( 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe', 'google-analytics-for-wordpress' ),
564
+ 'SA' => __( 'Saudi Arabia', 'google-analytics-for-wordpress' ),
565
+ 'SN' => __( 'Senegal', 'google-analytics-for-wordpress' ),
566
+ 'RS' => __( 'Serbia', 'google-analytics-for-wordpress' ),
567
+ 'SC' => __( 'Seychelles', 'google-analytics-for-wordpress' ),
568
+ 'SL' => __( 'Sierra Leone', 'google-analytics-for-wordpress' ),
569
+ 'SG' => __( 'Singapore', 'google-analytics-for-wordpress' ),
570
+ 'SK' => __( 'Slovak Republic', 'google-analytics-for-wordpress' ),
571
+ 'SI' => __( 'Slovenia', 'google-analytics-for-wordpress' ),
572
+ 'SB' => __( 'Solomon Islands', 'google-analytics-for-wordpress' ),
573
+ 'SO' => __( 'Somalia', 'google-analytics-for-wordpress' ),
574
+ 'ZA' => __( 'South Africa', 'google-analytics-for-wordpress' ),
575
+ 'GS' => __( 'South Georgia', 'google-analytics-for-wordpress' ),
576
+ 'KR' => __( 'South Korea', 'google-analytics-for-wordpress' ),
577
+ 'SS' => __( 'South Sudan', 'google-analytics-for-wordpress' ),
578
+ 'ES' => __( 'Spain', 'google-analytics-for-wordpress' ),
579
+ 'LK' => __( 'Sri Lanka', 'google-analytics-for-wordpress' ),
580
+ 'SD' => __( 'Sudan', 'google-analytics-for-wordpress' ),
581
+ 'SR' => __( 'Suriname', 'google-analytics-for-wordpress' ),
582
+ 'SJ' => __( 'Svalbard and Jan Mayen Islands', 'google-analytics-for-wordpress' ),
583
+ 'SZ' => __( 'Swaziland', 'google-analytics-for-wordpress' ),
584
+ 'SE' => __( 'Sweden', 'google-analytics-for-wordpress' ),
585
+ 'CH' => __( 'Switzerland', 'google-analytics-for-wordpress' ),
586
+ 'SY' => __( 'Syrian Arab Republic', 'google-analytics-for-wordpress' ),
587
+ 'TW' => __( 'Taiwan', 'google-analytics-for-wordpress' ),
588
+ 'TJ' => __( 'Tajikistan', 'google-analytics-for-wordpress' ),
589
+ 'TZ' => __( 'Tanzania', 'google-analytics-for-wordpress' ),
590
+ 'TH' => __( 'Thailand', 'google-analytics-for-wordpress' ),
591
+ 'TL' => __( 'Timor-Leste', 'google-analytics-for-wordpress' ),
592
+ 'TG' => __( 'Togo', 'google-analytics-for-wordpress' ),
593
+ 'TK' => __( 'Tokelau', 'google-analytics-for-wordpress' ),
594
+ 'TO' => __( 'Tonga', 'google-analytics-for-wordpress' ),
595
+ 'TT' => __( 'Trinidad and Tobago', 'google-analytics-for-wordpress' ),
596
+ 'TN' => __( 'Tunisia', 'google-analytics-for-wordpress' ),
597
+ 'TR' => __( 'Turkey', 'google-analytics-for-wordpress' ),
598
+ 'TM' => __( 'Turkmenistan', 'google-analytics-for-wordpress' ),
599
+ 'TC' => __( 'Turks and Caicos Islands', 'google-analytics-for-wordpress' ),
600
+ 'TV' => __( 'Tuvalu', 'google-analytics-for-wordpress' ),
601
+ 'UG' => __( 'Uganda', 'google-analytics-for-wordpress' ),
602
+ 'UA' => __( 'Ukraine', 'google-analytics-for-wordpress' ),
603
+ 'AE' => __( 'United Arab Emirates', 'google-analytics-for-wordpress' ),
604
+ 'UY' => __( 'Uruguay', 'google-analytics-for-wordpress' ),
605
+ 'UM' => __( 'US Minor Outlying Islands', 'google-analytics-for-wordpress' ),
606
+ 'UZ' => __( 'Uzbekistan', 'google-analytics-for-wordpress' ),
607
+ 'VU' => __( 'Vanuatu', 'google-analytics-for-wordpress' ),
608
+ 'VE' => __( 'Venezuela', 'google-analytics-for-wordpress' ),
609
+ 'VN' => __( 'Vietnam', 'google-analytics-for-wordpress' ),
610
+ 'VG' => __( 'Virgin Islands (British)', 'google-analytics-for-wordpress' ),
611
+ 'VI' => __( 'Virgin Islands (USA)', 'google-analytics-for-wordpress' ),
612
+ 'WF' => __( 'Wallis and Futuna Islands', 'google-analytics-for-wordpress' ),
613
+ 'EH' => __( 'Western Sahara', 'google-analytics-for-wordpress' ),
614
+ 'WS' => __( 'Western Samoa', 'google-analytics-for-wordpress' ),
615
+ 'YE' => __( 'Yemen', 'google-analytics-for-wordpress' ),
616
+ 'ZM' => __( 'Zambia', 'google-analytics-for-wordpress' ),
617
+ 'ZW' => __( 'Zimbabwe', 'google-analytics-for-wordpress' ),
618
+ );
619
+ } else {
620
+ $countries = array(
621
+ '' => '',
622
+ 'US' => 'United States',
623
+ 'CA' => 'Canada',
624
+ 'GB' => 'United Kingdom',
625
+ 'AF' => 'Afghanistan',
626
+ 'AX' => '&#197;land Islands',
627
+ 'AL' => 'Albania',
628
+ 'DZ' => 'Algeria',
629
+ 'AS' => 'American Samoa',
630
+ 'AD' => 'Andorra',
631
+ 'AO' => 'Angola',
632
+ 'AI' => 'Anguilla',
633
+ 'AQ' => 'Antarctica',
634
+ 'AG' => 'Antigua and Barbuda',
635
+ 'AR' => 'Argentina',
636
+ 'AM' => 'Armenia',
637
+ 'AW' => 'Aruba',
638
+ 'AU' => 'Australia',
639
+ 'AT' => 'Austria',
640
+ 'AZ' => 'Azerbaijan',
641
+ 'BS' => 'Bahamas',
642
+ 'BH' => 'Bahrain',
643
+ 'BD' => 'Bangladesh',
644
+ 'BB' => 'Barbados',
645
+ 'BY' => 'Belarus',
646
+ 'BE' => 'Belgium',
647
+ 'BZ' => 'Belize',
648
+ 'BJ' => 'Benin',
649
+ 'BM' => 'Bermuda',
650
+ 'BT' => 'Bhutan',
651
+ 'BO' => 'Bolivia',
652
+ 'BQ' => 'Bonaire, Saint Eustatius and Saba',
653
+ 'BA' => 'Bosnia and Herzegovina',
654
+ 'BW' => 'Botswana',
655
+ 'BV' => 'Bouvet Island',
656
+ 'BR' => 'Brazil',
657
+ 'IO' => 'British Indian Ocean Territory',
658
+ 'BN' => 'Brunei Darrussalam',
659
+ 'BG' => 'Bulgaria',
660
+ 'BF' => 'Burkina Faso',
661
+ 'BI' => 'Burundi',
662
+ 'KH' => 'Cambodia',
663
+ 'CM' => 'Cameroon',
664
+ 'CV' => 'Cape Verde',
665
+ 'KY' => 'Cayman Islands',
666
+ 'CF' => 'Central African Republic',
667
+ 'TD' => 'Chad',
668
+ 'CL' => 'Chile',
669
+ 'CN' => 'China',
670
+ 'CX' => 'Christmas Island',
671
+ 'CC' => 'Cocos Islands',
672
+ 'CO' => 'Colombia',
673
+ 'KM' => 'Comoros',
674
+ 'CD' => 'Congo, Democratic People\'s Republic',
675
+ 'CG' => 'Congo, Republic of',
676
+ 'CK' => 'Cook Islands',
677
+ 'CR' => 'Costa Rica',
678
+ 'CI' => 'Cote d\'Ivoire',
679
+ 'HR' => 'Croatia/Hrvatska',
680
+ 'CU' => 'Cuba',
681
+ 'CW' => 'Cura&Ccedil;ao',
682
+ 'CY' => 'Cyprus',
683
+ 'CZ' => 'Czechia',
684
+ 'DK' => 'Denmark',
685
+ 'DJ' => 'Djibouti',
686
+ 'DM' => 'Dominica',
687
+ 'DO' => 'Dominican Republic',
688
+ 'TP' => 'East Timor',
689
+ 'EC' => 'Ecuador',
690
+ 'EG' => 'Egypt',
691
+ 'GQ' => 'Equatorial Guinea',
692
+ 'SV' => 'El Salvador',
693
+ 'ER' => 'Eritrea',
694
+ 'EE' => 'Estonia',
695
+ 'ET' => 'Ethiopia',
696
+ 'FK' => 'Falkland Islands',
697
+ 'FO' => 'Faroe Islands',
698
+ 'FJ' => 'Fiji',
699
+ 'FI' => 'Finland',
700
+ 'FR' => 'France',
701
+ 'GF' => 'French Guiana',
702
+ 'PF' => 'French Polynesia',
703
+ 'TF' => 'French Southern Territories',
704
+ 'GA' => 'Gabon',
705
+ 'GM' => 'Gambia',
706
+ 'GE' => 'Georgia',
707
+ 'DE' => 'Germany',
708
+ 'GR' => 'Greece',
709
+ 'GH' => 'Ghana',
710
+ 'GI' => 'Gibraltar',
711
+ 'GL' => 'Greenland',
712
+ 'GD' => 'Grenada',
713
+ 'GP' => 'Guadeloupe',
714
+ 'GU' => 'Guam',
715
+ 'GT' => 'Guatemala',
716
+ 'GG' => 'Guernsey',
717
+ 'GN' => 'Guinea',
718
+ 'GW' => 'Guinea-Bissau',
719
+ 'GY' => 'Guyana',
720
+ 'HT' => 'Haiti',
721
+ 'HM' => 'Heard and McDonald Islands',
722
+ 'VA' => 'Holy See (City Vatican State)',
723
+ 'HN' => 'Honduras',
724
+ 'HK' => 'Hong Kong',
725
+ 'HU' => 'Hungary',
726
+ 'IS' => 'Iceland',
727
+ 'IN' => 'India',
728
+ 'ID' => 'Indonesia',
729
+ 'IR' => 'Iran',
730
+ 'IQ' => 'Iraq',
731
+ 'IE' => 'Ireland',
732
+ 'IM' => 'Isle of Man',
733
+ 'IL' => 'Israel',
734
+ 'IT' => 'Italy',
735
+ 'JM' => 'Jamaica',
736
+ 'JP' => 'Japan',
737
+ 'JE' => 'Jersey',
738
+ 'JO' => 'Jordan',
739
+ 'KZ' => 'Kazakhstan',
740
+ 'KE' => 'Kenya',
741
+ 'KI' => 'Kiribati',
742
+ 'KW' => 'Kuwait',
743
+ 'KG' => 'Kyrgyzstan',
744
+ 'LA' => 'Lao People\'s Democratic Republic',
745
+ 'LV' => 'Latvia',
746
+ 'LB' => 'Lebanon',
747
+ 'LS' => 'Lesotho',
748
+ 'LR' => 'Liberia',
749
+ 'LY' => 'Libyan Arab Jamahiriya',
750
+ 'LI' => 'Liechtenstein',
751
+ 'LT' => 'Lithuania',
752
+ 'LU' => 'Luxembourg',
753
+ 'MO' => 'Macau',
754
+ 'MK' => 'Macedonia',
755
+ 'MG' => 'Madagascar',
756
+ 'MW' => 'Malawi',
757
+ 'MY' => 'Malaysia',
758
+ 'MV' => 'Maldives',
759
+ 'ML' => 'Mali',
760
+ 'MT' => 'Malta',
761
+ 'MH' => 'Marshall Islands',
762
+ 'MQ' => 'Martinique',
763
+ 'MR' => 'Mauritania',
764
+ 'MU' => 'Mauritius',
765
+ 'YT' => 'Mayotte',
766
+ 'MX' => 'Mexico',
767
+ 'FM' => 'Micronesia',
768
+ 'MD' => 'Moldova, Republic of',
769
+ 'MC' => 'Monaco',
770
+ 'MN' => 'Mongolia',
771
+ 'ME' => 'Montenegro',
772
+ 'MS' => 'Montserrat',
773
+ 'MA' => 'Morocco',
774
+ 'MZ' => 'Mozambique',
775
+ 'MM' => 'Myanmar (Burma)',
776
+ 'NA' => 'Namibia',
777
+ 'NR' => 'Nauru',
778
+ 'NP' => 'Nepal',
779
+ 'NL' => 'Netherlands',
780
+ 'AN' => 'Netherlands Antilles',
781
+ 'NC' => 'New Caledonia',
782
+ 'NZ' => 'New Zealand',
783
+ 'NI' => 'Nicaragua',
784
+ 'NE' => 'Niger',
785
+ 'NG' => 'Nigeria',
786
+ 'NU' => 'Niue',
787
+ 'NF' => 'Norfolk Island',
788
+ 'KP' => 'North Korea',
789
+ 'MP' => 'Northern Mariana Islands',
790
+ 'NO' => 'Norway',
791
+ 'OM' => 'Oman',
792
+ 'PK' => 'Pakistan',
793
+ 'PW' => 'Palau',
794
+ 'PS' => 'Palestinian Territories',
795
+ 'PA' => 'Panama',
796
+ 'PG' => 'Papua New Guinea',
797
+ 'PY' => 'Paraguay',
798
+ 'PE' => 'Peru',
799
+ 'PH' => 'Philippines',
800
+ 'PN' => 'Pitcairn Island',
801
+ 'PL' => 'Poland',
802
+ 'PT' => 'Portugal',
803
+ 'PR' => 'Puerto Rico',
804
+ 'QA' => 'Qatar',
805
+ 'XK' => 'Republic of Kosovo',
806
+ 'RE' => 'Reunion Island',
807
+ 'RO' => 'Romania',
808
+ 'RU' => 'Russia',
809
+ 'RW' => 'Rwanda',
810
+ 'BL' => 'Saint Barth&eacute;lemy',
811
+ 'SH' => 'Saint Helena',
812
+ 'KN' => 'Saint Kitts and Nevis',
813
+ 'LC' => 'Saint Lucia',
814
+ 'MF' => 'Saint Martin (French)',
815
+ 'SX' => 'Saint Martin (Dutch)',
816
+ 'PM' => 'Saint Pierre and Miquelon',
817
+ 'VC' => 'Saint Vincent and the Grenadines',
818
+ 'SM' => 'San Marino',
819
+ 'ST' => 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe',
820
+ 'SA' => 'Saudi Arabia',
821
+ 'SN' => 'Senegal',
822
+ 'RS' => 'Serbia',
823
+ 'SC' => 'Seychelles',
824
+ 'SL' => 'Sierra Leone',
825
+ 'SG' => 'Singapore',
826
+ 'SK' => 'Slovak Republic',
827
+ 'SI' => 'Slovenia',
828
+ 'SB' => 'Solomon Islands',
829
+ 'SO' => 'Somalia',
830
+ 'ZA' => 'South Africa',
831
+ 'GS' => 'South Georgia',
832
+ 'KR' => 'South Korea',
833
+ 'SS' => 'South Sudan',
834
+ 'ES' => 'Spain',
835
+ 'LK' => 'Sri Lanka',
836
+ 'SD' => 'Sudan',
837
+ 'SR' => 'Suriname',
838
+ 'SJ' => 'Svalbard and Jan Mayen Islands',
839
+ 'SZ' => 'Swaziland',
840
+ 'SE' => 'Sweden',
841
+ 'CH' => 'Switzerland',
842
+ 'SY' => 'Syrian Arab Republic',
843
+ 'TW' => 'Taiwan',
844
+ 'TJ' => 'Tajikistan',
845
+ 'TZ' => 'Tanzania',
846
+ 'TH' => 'Thailand',
847
+ 'TL' => 'Timor-Leste',
848
+ 'TG' => 'Togo',
849
+ 'TK' => 'Tokelau',
850
+ 'TO' => 'Tonga',
851
+ 'TT' => 'Trinidad and Tobago',
852
+ 'TN' => 'Tunisia',
853
+ 'TR' => 'Turkey',
854
+ 'TM' => 'Turkmenistan',
855
+ 'TC' => 'Turks and Caicos Islands',
856
+ 'TV' => 'Tuvalu',
857
+ 'UG' => 'Uganda',
858
+ 'UA' => 'Ukraine',
859
+ 'AE' => 'United Arab Emirates',
860
+ 'UY' => 'Uruguay',
861
+ 'UM' => 'US Minor Outlying Islands',
862
+ 'UZ' => 'Uzbekistan',
863
+ 'VU' => 'Vanuatu',
864
+ 'VE' => 'Venezuela',
865
+ 'VN' => 'Vietnam',
866
+ 'VG' => 'Virgin Islands (British)',
867
+ 'VI' => 'Virgin Islands (USA)',
868
+ 'WF' => 'Wallis and Futuna Islands',
869
+ 'EH' => 'Western Sahara',
870
+ 'WS' => 'Western Samoa',
871
+ 'YE' => 'Yemen',
872
+ 'ZM' => 'Zambia',
873
+ 'ZW' => 'Zimbabwe',
874
+ );
875
+ }
876
+ return $countries;
877
+ }
878
+
879
+ function monsterinsights_get_api_url(){
880
+ return apply_filters( 'monsterinsights_get_api_url', 'api.monsterinsights.com/v2/' );
881
+ }
882
+
883
+ function monsterinsights_get_licensing_url(){
884
+ return apply_filters( 'monsterinsights_get_licensing_url', 'https://www.monsterinsights.com' );
885
+ }
886
+
887
+ function monsterinsights_is_wp_seo_active( ) {
888
+ $wp_seo_active = false; // @todo: improve this check. This is from old Yoast code.
889
+
890
+ // Makes sure is_plugin_active is available when called from front end
891
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
892
+ if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) || is_plugin_active( 'wordpress-seo-premium/wp-seo-premium.php' ) ) {
893
+ $wp_seo_active = true;
894
+ }
895
+ return $wp_seo_active;
896
+ }
897
+
898
+ function monsterinsights_get_asset_version() {
899
+ if ( monsterinsights_is_debug_mode() || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ) {
900
+ return time();
901
+ } else {
902
+ return MONSTERINSIGHTS_VERSION;
903
+ }
904
+ }
905
+
906
+ function monsterinsights_is_debug_mode() {
907
+ $debug_mode = false;
908
+ if ( defined( 'MONSTERINSIGHTS_DEBUG_MODE' ) && MONSTERINSIGHTS_DEBUG_MODE ) {
909
+ $debug_mode = true;
910
+ }
911
+
912
+ return apply_filters( 'monsterinsights_is_debug_mode', $debug_mode );
913
+ }
914
+
915
+ function monsterinsights_is_network_active() {
916
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
917
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
918
+ }
919
+
920
+ if ( is_multisite() && is_plugin_active_for_network( plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ) ) ) {
921
+ return true;
922
+ } else {
923
+ return false;
924
+ }
925
+ }
926
+
927
+ if ( ! function_exists ( 'remove_class_filter' ) ) {
928
+ /**
929
+ * Remove Class Filter Without Access to Class Object
930
+ *
931
+ * In order to use the core WordPress remove_filter() on a filter added with the callback
932
+ * to a class, you either have to have access to that class object, or it has to be a call
933
+ * to a static method. This method allows you to remove filters with a callback to a class
934
+ * you don't have access to.
935
+ *
936
+ * Works with WordPress 1.2 - 4.7+
937
+ *
938
+ * @param string $tag Filter to remove
939
+ * @param string $class_name Class name for the filter's callback
940
+ * @param string $method_name Method name for the filter's callback
941
+ * @param int $priority Priority of the filter (default 10)
942
+ *
943
+ * @return bool Whether the function is removed.
944
+ */
945
+ function remove_class_filter( $tag, $class_name = '', $method_name = '', $priority = 10 ) {
946
+ global $wp_filter;
947
+ // Check that filter actually exists first
948
+ if ( ! isset( $wp_filter[ $tag ] ) ) return FALSE;
949
+ /**
950
+ * If filter config is an object, means we're using WordPress 4.7+ and the config is no longer
951
+ * a simple array, rather it is an object that implements the ArrayAccess interface.
952
+ *
953
+ * To be backwards compatible, we set $callbacks equal to the correct array as a reference (so $wp_filter is updated)
954
+ *
955
+ * @see https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/
956
+ */
957
+ if ( is_object( $wp_filter[ $tag ] ) && isset( $wp_filter[ $tag ]->callbacks ) ) {
958
+ $callbacks = &$wp_filter[ $tag ]->callbacks;
959
+ } else {
960
+ $callbacks = &$wp_filter[ $tag ];
961
+ }
962
+ // Exit if there aren't any callbacks for specified priority
963
+ if ( ! isset( $callbacks[ $priority ] ) || empty( $callbacks[ $priority ] ) ) return FALSE;
964
+ // Loop through each filter for the specified priority, looking for our class & method
965
+ foreach( (array) $callbacks[ $priority ] as $filter_id => $filter ) {
966
+ // Filter should always be an array - array( $this, 'method' ), if not goto next
967
+ if ( ! isset( $filter[ 'function' ] ) || ! is_array( $filter[ 'function' ] ) ) continue;
968
+ // If first value in array is not an object, it can't be a class
969
+ if ( ! is_object( $filter[ 'function' ][ 0 ] ) ) continue;
970
+ // Method doesn't match the one we're looking for, goto next
971
+ if ( $filter[ 'function' ][ 1 ] !== $method_name ) continue;
972
+ // Method matched, now let's check the Class
973
+ if ( get_class( $filter[ 'function' ][ 0 ] ) === $class_name ) {
974
+ // Now let's remove it from the array
975
+ unset( $callbacks[ $priority ][ $filter_id ] );
976
+ // and if it was the only filter in that priority, unset that priority
977
+ if ( empty( $callbacks[ $priority ] ) ) unset( $callbacks[ $priority ] );
978
+ // and if the only filter for that tag, set the tag to an empty array
979
+ if ( empty( $callbacks ) ) $callbacks = array();
980
+ // If using WordPress older than 4.7
981
+ if ( ! is_object( $wp_filter[ $tag ] ) ) {
982
+ // Remove this filter from merged_filters, which specifies if filters have been sorted
983
+ unset( $GLOBALS[ 'merged_filters' ][ $tag ] );
984
+ }
985
+ return TRUE;
986
+ }
987
+ }
988
+ return FALSE;
989
+ }
990
+ } // End function exists
991
+
992
+ if ( ! function_exists ( 'remove_class_action' ) ) {
993
+ /**
994
+ * Remove Class Action Without Access to Class Object
995
+ *
996
+ * In order to use the core WordPress remove_action() on an action added with the callback
997
+ * to a class, you either have to have access to that class object, or it has to be a call
998
+ * to a static method. This method allows you to remove actions with a callback to a class
999
+ * you don't have access to.
1000
+ *
1001
+ * Works with WordPress 1.2 - 4.7+
1002
+ *
1003
+ * @param string $tag Action to remove
1004
+ * @param string $class_name Class name for the action's callback
1005
+ * @param string $method_name Method name for the action's callback
1006
+ * @param int $priority Priority of the action (default 10)
1007
+ *
1008
+ * @return bool Whether the function is removed.
1009
+ */
1010
+ function remove_class_action( $tag, $class_name = '', $method_name = '', $priority = 10 ) {
1011
+ remove_class_filter( $tag, $class_name, $method_name, $priority );
1012
+ }
1013
+ } // End function exists
1014
+
1015
+ /**
1016
+ * Format a big number, instead of 1000000 you get 1.0M, works with billions also.
1017
+ *
1018
+ * @param int $number
1019
+ * @param int $precision
1020
+ *
1021
+ * @return string
1022
+ */
1023
+ function monsterinsights_round_number( $number, $precision = 2 ) {
1024
+
1025
+ if ( $number < 1000000 ) {
1026
+ // Anything less than a million
1027
+ $number = number_format_i18n( $number );
1028
+ } else if ( $number < 1000000000 ) {
1029
+ // Anything less than a billion
1030
+ $number = number_format_i18n( $number / 1000000, $precision ) . 'M';
1031
+ } else {
1032
+ // At least a billion
1033
+ $number = number_format_i18n( $number / 1000000000, $precision ) . 'B';
1034
+ }
1035
+
1036
+ return $number;
1037
+ }
1038
+
1039
+ if ( ! function_exists( 'wp_get_jed_locale_data' ) ) {
1040
+ /**
1041
+ * Returns Jed-formatted localization data. Added for backwards-compatibility.
1042
+ *
1043
+ * @param string $domain Translation domain.
1044
+ *
1045
+ * @return array
1046
+ */
1047
+ function wp_get_jed_locale_data( $domain ) {
1048
+ $translations = get_translations_for_domain( $domain );
1049
+
1050
+ $locale = array(
1051
+ '' => array(
1052
+ 'domain' => $domain,
1053
+ 'lang' => is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
1054
+ ),
1055
+ );
1056
+
1057
+ if ( ! empty( $translations->headers['Plural-Forms'] ) ) {
1058
+ $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
1059
+ }
1060
+
1061
+ foreach ( $translations->entries as $msgid => $entry ) {
1062
+ $locale[ $msgid ] = $entry->translations;
1063
+ }
1064
+
1065
+ return $locale;
1066
+ }
1067
+ }
1068
+
1069
+ function monsterinsights_get_inline_menu_icon() {
1070
+ $scheme = get_user_option( 'admin_color', get_current_user_id() );
1071
+ $use_dark_scheme = $scheme === 'light';
1072
+ if ( $use_dark_scheme ) {
1073
+ return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAFQUlEQVRYha2Yb2hXZRTHP+c3nc6pm07NF0KWWUtSo0wqzBdiZRItTKMaEZXSi0zRNAsqTBKKSFOa0B8Jigqz2lSwLMtqRURgRuCCLLNmselyZups2+/04pzbnt3de3eTDlzufc5znvN8n+ec55zzXFFV8pKITANOqmpTP3JTgIKq7sutPCJVzfUABeAb4DSwMENuKdABNObV3Wv8fwB0C6DAUX8/67sQ9Q8ANsVk5v5vgIDKWHsvcAgYCWzzCbc6kFJgh/PqgVHAb8DnWTpzA3LzHARmeXuqT/Zo0L/eeZuAV/x7fbRrwJPOu9Dbc4EDgJwNoMmurAt4Bljt7cmBjACvOl+BzTEdVzj/EWAj0O3tC84G0AIf3BRMeDz0GZcbBvzqKy+L9Q30A6AxXTdmARqQcPAAyv29CBjjO1RU1SKAiIwGFgLX+MrbgBnAh5ECVe0UkUMO6nHgFLA70J1McacD5gHbfTXzg77qwBeOBysPn830PnnVwXety7wL1AAV/ZoM+MIHdQCfAdfF+s8H/koBEz0rU9xgLtAInHG5j/KYrNWf8ap6OmFD7w+2/Cugwd/NmOkqgbIUS+wEdorIEOAwFqv6UBKgihQwANNc0b2quh1ARIZi/nUqZUycOrDDcCSps5AAaJBPkkStwNVAs4i8JiLHgBPASRFpFZEGEZktIpIBqBIoIWWH4nZegtl3fIofjAKeoyemfAe8hZnu64D/NjAsRcdEl1mcx6lvc+HLU6L3O97/JXBlgszF9KSVvXhswkxUC6wLdKzIA2iWC1+fMNlK72sASlMjrQHf4LIvAw8B7fScwmNAZ7DDs7MARSmjNsYf7oqak0wBjAXuBlb5Lo9wE0Yg6rHAOdjlR2KB9Qc384o0QOe4giUx/u3OX5oA5gEsCoexqBnYAxTTfMXHlvuOF4F5SYBKHPGaGH+jTzQxxefSnnVpYAIdg9x0PwEDkwSOAHUx3hafoDzGP5AB5gQ56h/XU+NjauJxCCxRjo7xOvw9ImKISBUwIWF8RLtVtT2jP6SdWBKe1QuQiCwDLsKcNKSoqJ8e8BJTREAHc4JBVTuBn4Gx/wISkflYndyNOXdI2/29OOAd7mfSIXkBOZUDxTACt2A78SLQnmDnBszOiwLeraT70Ld5/Mf1jPMxqyLGWqxcnYoFMqVvBTgOK9y7gOVAifMfdF4SqJk5Aa3FLFMNduxagQbvvJOUfIb51/f0lKSrsROyHCtlIyDtrrMJqOoHzAysRvrA28wmSBfAtd7uk6u8vwwr/JOqxm4sl01wvZ3AfhJyo+taAPyJhYi/gekCPIXdNitV9YyIXIIFqptVdVsf13MSkVJgJlZF4rvSqKq/BzJzgNexcPEp8LFPXAHcAFzqoKcAddjR5z2Cay/m4Arcl9cp+zFJFfA0dslMOwB1wD1AewGrTw4Ei2/zVcSP/lmRqrap6irs8gAwid7xDOAuzNwlgmXxF1T14ahXRPZjtU1k3+g5Tk8pkUUFzCwVWC003N/DgGVYIXheIF/EfmQcFczDW4DnsVtBCxbUtmIOPAAzY6MPLgMG+/dlDrIADHWlYL4QpZuZWLjYgp3SOb7QMbFFFLF6LDNB7sGcri7FP7qwWmcX9t8oSWaDA6zCqomXUuZ6U1UpYDXxH5jfgKWET/y7zXfolIgkJeJMEpES/xwMXKWq3aq6CLu9PAH8Eog/Fn2UYnlkDWa2c719E3Y/f8NX0AL8GHuianAXtuXx/lZ6brR9/npgcWgHcEfEkyg6ZqyyBrt1ptE+X9SkDJl6VX0/cyKnfwBb6gwNaZ8ExgAAAABJRU5ErkJggg';
1074
+ } else {
1075
+ return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AoEBjcfBsDvpwAABQBJREFUWMO1mGmollUQgJ9z79Vc01LLH0GLWRqlUhYV5o+LbRIVbVQSUSn9qJTKsqDCoqCINKUbtBEUFbbeDGyz1SIiaCHIINu18KZ1bbkuV+/Tj+arw8v7fvdVcuDjvGdmzsycM3Nm5nywE6BOVSfW4JukTmF3gtqifqJuVmc34ZunblFX7W6DzvYf2BDjPWpLRm9T7y/wzPw/DRhZmH+sfq/urb4YCp8JQwaqLwXuBXW0+pP6XjOZO+ueb9X2mE8OZTdl9MWBu199NL4XN05NvT1wh8R8prpGTbti0BEhbLt6t7ow5kdkPEl9zP/gkYKMowN/o7pU3RHzg3fFoHNj8epM4aY8ZoJvuPpj7HxwgTYgLoAFWac1091WgR8a4xxgH2Ah0JdS6gtlY4DZwAnADmAjMA14vSEgpdSrfg9sBm4BeoCVmex6gayepS6P3ZyT0SZksbDJcnikcPMmZN+zgud59Qx1RB2D3o9FW9R31ZMK9IPUP20O11XInqmuUrcG3xt1XNYVvwNSSptL+K/IjvxDoDPGteG6kcDgMkUppRXACnUIsA7YUNegERXGAEwNQZellJbHzodFfPXUjIwtwHDglzJiS4lBe4SSMugCjgfWqo+rvwF/AH+pXWqnOqOfXDMSaK06oaKf54Z/D6igj1bvzXLK5+rTYchHGf5ZdXiFjPHBc2Udg84P5qMqsvdzQf9APbaEZ2JWVj5u5KbIV7PURZmM+XUMag/mk0to1wWtUx3YT9lZErwPq9er3dkt/E3tzU54Rp2SMauA3zMErS1zhTpWvURdEKe8V7jQrOBOUwcF/97qbPWrcPP8KoP2DQFzC/gLAj+vZM1Vak8hF61V31L7msWKOjROvE89q4yhNSy+rYBfGorGV8RcFSyqESZ7hOu+UQeUMfyidhRwy0LB0AJ+TRNj/qjb/0QpUT2jpYS+ERhTkswA9sqEjALGNdGzMqXUXTNZrogi3F5sJ64GDgXGFhasjvGYDDe4HyXf1i3qKaVe4DtgbF6ZzwHuiZq0b2HN8hjzAF3Xj9IhO9mGDQX68gy8PpqoB9XuEj93hp/nZLjzmsTQZzvR9uwXaxY0EHdEuzo5EpklHeB+0bhvV69RWwN/beDKYHpNg+6I2z2hce261M4gXlRVz9RD1S+zlnRh3JBropVtQHfIXB3B38yYadEjvdZAzMjLhXpizI+tEDA4Gv+yrnFH1LJxIbdX/aKsNma9+++RIrapxyT1TmAeMDKltFU9HPgcODOl9GKTnQ0EpgMHBaobWJVS+jnjOQV4ItLFO8CbwDZgBHAqMAXoBSYBHcBm1JfzZ28EuOrl/9ODc5R6Vzwyq6BDvVTtbgHGA2sKiXFbydXfJUgpbUwpLQAateqwQj4DuDjSTWuKru+BlNIN2a6+ACYCv0dH2PhtCtfYjx0t4ZYR0a7uGeNw4GpgLnBgxt8HfAJsSOpWYD1wH7AqvocAz0Q2bgNGB62RoQfF95FhZAswLIQSZaBRbqYDPwHLogqcEhvdp7CJPqC9vwL5VtyUjor42B69zqvqXxU8S+IFOyq6iYcqdD3VONqngV8jbhol4e0sntqAnuIzumZAt8bnIOC4lNKOlNKceL3cCvyQsd/87/WNRuk29T51/5ifHu/zJ2MH69WvCz+zE+oroXdlL9pUkYdeUi/89xLU6VWAZn88fQoMjNtTBS+klF6pc6p/A2ye4OCYzm1lAAAAAElFTkSuQmCC';
1076
+ }
1077
+ }
1078
+
1079
+
1080
+ function monsterinsights_get_shareasale_id() {
1081
+ // Check if there's a constant.
1082
+ $shareasale_id = '';
1083
+ if ( defined( 'MONSTERINSIGHTS_SHAREASALE_ID' ) ) {
1084
+ $shareasale_id = MONSTERINSIGHTS_SHAREASALE_ID;
1085
+ }
1086
+
1087
+ // If there's no constant, check if there's an option.
1088
+ if ( empty( $shareasale_id ) ) {
1089
+ $shareasale_id = get_option( 'monsterinsights_shareasale_id', '' );
1090
+ }
1091
+
1092
+ // Whether we have an ID or not, filter the ID.
1093
+ $shareasale_id = apply_filters( 'monsterinsights_shareasale_id', $shareasale_id );
1094
+
1095
+ // Ensure it's a number
1096
+ $shareasale_id = absint( $shareasale_id );
1097
+
1098
+ return $shareasale_id;
1099
+ }
1100
+
1101
+ // Passed in with mandatory default redirect and shareasaleid from monsterinsights_get_upgrade_link
1102
+ function monsterinsights_get_shareasale_url( $shareasale_id, $shareasale_redirect ) {
1103
+ // Check if there's a constant.
1104
+ $custom = false;
1105
+ if ( defined( 'MONSTERINSIGHTS_SHAREASALE_REDIRECT_URL' ) ) {
1106
+ $shareasale_redirect = MONSTERINSIGHTS_SHAREASALE_REDIRECT_URL;
1107
+ $custom = true;
1108
+ }
1109
+
1110
+ // If there's no constant, check if there's an option.
1111
+ if ( empty( $custom ) ) {
1112
+ $shareasale_redirect = get_option( 'monsterinsights_shareasale_redirect_url', '' );
1113
+ $custom = true;
1114
+ }
1115
+
1116
+ // Whether we have an ID or not, filter the ID.
1117
+ $shareasale_redirect = apply_filters( 'monsterinsights_shareasale_redirect_url', $shareasale_redirect, $custom );
1118
+ $shareasale_url = sprintf( 'https://www.shareasale.com/r.cfm?B=971799&U=%s&M=69975&urllink=%s', $shareasale_id, $shareasale_redirect );
1119
+
1120
+ return $shareasale_url;
1121
+ }
1122
+
1123
+ /**
1124
+ * Get a clean page title for archives.
1125
+ */
1126
+ function monsterinsights_get_page_title() {
1127
+
1128
+ $title = __( 'Archives' );
1129
+
1130
+ if ( is_category() ) {
1131
+ /* translators: Category archive title. %s: Category name */
1132
+ $title = sprintf( __( 'Category: %s' ), single_cat_title( '', false ) );
1133
+ } elseif ( is_tag() ) {
1134
+ /* translators: Tag archive title. %s: Tag name */
1135
+ $title = sprintf( __( 'Tag: %s' ), single_tag_title( '', false ) );
1136
+ } elseif ( is_author() ) {
1137
+ /* translators: Author archive title. %s: Author name */
1138
+ $title = sprintf( __( 'Author: %s' ), '<span class="vcard">' . get_the_author() . '</span>' );
1139
+ } elseif ( is_year() ) {
1140
+ /* translators: Yearly archive title. %s: Year */
1141
+ $title = sprintf( __( 'Year: %s' ), get_the_date( _x( 'Y', 'yearly archives date format' ) ) );
1142
+ } elseif ( is_month() ) {
1143
+ /* translators: Monthly archive title. %s: Month name and year */
1144
+ $title = sprintf( __( 'Month: %s' ), get_the_date( _x( 'F Y', 'monthly archives date format' ) ) );
1145
+ } elseif ( is_day() ) {
1146
+ /* translators: Daily archive title. %s: Date */
1147
+ $title = sprintf( __( 'Day: %s' ), get_the_date( _x( 'F j, Y', 'daily archives date format' ) ) );
1148
+ } elseif ( is_tax( 'post_format' ) ) {
1149
+ if ( is_tax( 'post_format', 'post-format-aside' ) ) {
1150
+ $title = _x( 'Asides', 'post format archive title' );
1151
+ } elseif ( is_tax( 'post_format', 'post-format-gallery' ) ) {
1152
+ $title = _x( 'Galleries', 'post format archive title' );
1153
+ } elseif ( is_tax( 'post_format', 'post-format-image' ) ) {
1154
+ $title = _x( 'Images', 'post format archive title' );
1155
+ } elseif ( is_tax( 'post_format', 'post-format-video' ) ) {
1156
+ $title = _x( 'Videos', 'post format archive title' );
1157
+ } elseif ( is_tax( 'post_format', 'post-format-quote' ) ) {
1158
+ $title = _x( 'Quotes', 'post format archive title' );
1159
+ } elseif ( is_tax( 'post_format', 'post-format-link' ) ) {
1160
+ $title = _x( 'Links', 'post format archive title' );
1161
+ } elseif ( is_tax( 'post_format', 'post-format-status' ) ) {
1162
+ $title = _x( 'Statuses', 'post format archive title' );
1163
+ } elseif ( is_tax( 'post_format', 'post-format-audio' ) ) {
1164
+ $title = _x( 'Audio', 'post format archive title' );
1165
+ } elseif ( is_tax( 'post_format', 'post-format-chat' ) ) {
1166
+ $title = _x( 'Chats', 'post format archive title' );
1167
+ }
1168
+ } elseif ( is_post_type_archive() ) {
1169
+ /* translators: Post type archive title. %s: Post type name */
1170
+ $title = sprintf( __( 'Archives: %s' ), post_type_archive_title( '', false ) );
1171
+ } elseif ( is_tax() ) {
1172
+ $tax = get_taxonomy( get_queried_object()->taxonomy );
1173
+ /* translators: Taxonomy term archive title. 1: Taxonomy singular name, 2: Current taxonomy term */
1174
+ $title = sprintf( __( '%1$s: %2$s' ), $tax->labels->singular_name, single_term_title( '', false ) );
1175
+ }
1176
+
1177
+ return $title;
1178
+
1179
+ }
1180
+
1181
+ /**
1182
+ * Make a request to the front page and check if the tracking code is present. Moved here from onboarding wizard
1183
+ * to be used in the site health check.
1184
+ *
1185
+ * @return array
1186
+ */
1187
+ function monsterinsights_is_code_installed_frontend() {
1188
+ // Grab the front page html.
1189
+ $request = wp_remote_request( home_url(), array(
1190
+ 'sslverify' => false,
1191
+ ) );
1192
+ $errors = array();
1193
+
1194
+ if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
1195
+
1196
+ $body = wp_remote_retrieve_body( $request );
1197
+ $current_ua_code = monsterinsights_get_ua_to_output();
1198
+ $ua_limit = 2;
1199
+ // If the ads addon is installed another UA is added to the page.
1200
+ if ( class_exists( 'MonsterInsights_Ads' ) ) {
1201
+ $ua_limit = 3;
1202
+ }
1203
+ // Translators: The placeholders are for making the "We noticed you're using a caching plugin" text bold.
1204
+ $cache_error = sprintf( esc_html__( '%1$sWe noticed you\'re using a caching plugin or caching from your hosting provider.%2$s Be sure to clear the cache to ensure the tracking appears on all pages and posts. %3$s(See this guide on how to clear cache)%4$s.', 'google-analytics-for-wordpress' ), '<b>', '</b>', ' <a href="https://www.wpbeginner.com/beginners-guide/how-to-clear-your-cache-in-wordpress/" target="_blank">', '</a>' );
1205
+ // Translators: The placeholders are for making the "We have detected multiple tracking codes" text bold & adding a link to support.
1206
+ $multiple_ua_error = sprintf( esc_html__( '%1$sWe have detected multiple tracking codes%2$s! You should remove non-MonsterInsights ones. If you need help finding them please %3$sread this article%4$s.', 'google-analytics-for-wordpress' ), '<b>', '</b>', '<a href="https://www.monsterinsights.com/docs/how-to-find-duplicate-google-analytics-tracking-codes-in-wordpress/" target="_blank">', '</a>' );
1207
+
1208
+ // First, check if the tracking frontend code is present.
1209
+ if ( false === strpos( $body, '__gaTracker' ) ) {
1210
+ $errors[] = $cache_error;
1211
+ } else {
1212
+ // Check if the current UA code is actually present.
1213
+ if ( $current_ua_code && false === strpos( $body, $current_ua_code ) ) {
1214
+ // We have the tracking code but using another UA, so it's cached.
1215
+ $errors[] = $cache_error;
1216
+ }
1217
+ // Grab all the UA codes from the page.
1218
+ $pattern = '/UA-[0-9]+/m';
1219
+ preg_match_all( $pattern, $body, $matches );
1220
+ // If more than twice ( because MI has a ga-disable-UA also ), let them know to remove the others.
1221
+ if ( ! empty( $matches[0] ) && is_array( $matches[0] ) && count( $matches[0] ) > $ua_limit ) {
1222
+ $errors[] = $multiple_ua_error;
1223
+ }
1224
+ }
1225
+ }
1226
+
1227
+ return $errors;
1228
+ }
1229
+
1230
+ /**
1231
+ * Returns a HEX color to highlight menu items based on the admin color scheme.
1232
+ */
1233
+ function monsterinsights_menu_highlight_color() {
1234
+
1235
+ $color_scheme = get_user_option( 'admin_color' );
1236
+ $color = '#7cc048';
1237
+ if ( 'light' === $color_scheme || 'blue' === $color_scheme ) {
1238
+ $color = '#5f3ea7';
1239
+ }
1240
+
1241
+ return $color;
1242
+ }
includes/index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
includes/install.php CHANGED
@@ -1,544 +1,590 @@
1
- <?php
2
- /**
3
- * MonsterInsights Installation and Automatic Upgrades.
4
- *
5
- * This file handles setting up new
6
- * MonsterInsights installs as well as performing
7
- * behind the scene upgrades between
8
- * MonsterInsights versions.
9
- *
10
- * @package MonsterInsights
11
- * @subpackage Install/Upgrade
12
- * @since 6.0.0
13
- */
14
-
15
- // Exit if accessed directly
16
- if ( ! defined( 'ABSPATH' ) ) {
17
- exit;
18
- }
19
-
20
- /**
21
- * MonsterInsights Install.
22
- *
23
- * This class handles a new MI install
24
- * as well as automatic (non-user initiated)
25
- * upgrade routines.
26
- *
27
- * @since 6.0.0
28
- * @access public
29
- */
30
- class MonsterInsights_Install {
31
-
32
- /**
33
- * MI Settings.
34
- *
35
- * @since 6.0.0
36
- * @access public
37
- * @var array $new_settings When the init() function starts, initially
38
- * contains the original settings. At the end
39
- * of init() contains the settings to save.
40
- */
41
- public $new_settings = array();
42
-
43
- /**
44
- * Install/Upgrade routine.
45
- *
46
- * This function is what is called to actually install MI data on new installs and to do
47
- * behind the scenes upgrades on MI upgrades. If this function contains a bug, the results
48
- * can be catastrophic. This function gets the highest priority in all of MI for unit tests.
49
- *
50
- * @since 6.0.0
51
- * @access public
52
- *
53
- * @return void
54
- */
55
- public function init() {
56
-
57
- // Get a copy of the current MI settings.
58
- $this->new_settings = get_option( monsterinsights_get_option_name() );
59
-
60
- $version = get_option( 'monsterinsights_current_version', false );
61
- $cachec = false; // have we forced an object cache to be cleared already (so we don't clear it unnecessarily)
62
-
63
- // if new install or Yoast Era instal
64
- if ( ! $version ) {
65
- // See if from Yoast
66
- $yoast = get_option( 'yst_ga', false );
67
-
68
- // In case from Yoast, start from scratch
69
- delete_option( 'yoast-ga-access_token' );
70
- delete_option( 'yoast-ga-refresh_token' );
71
- delete_option( 'yst_ga' );
72
- delete_option( 'yst_ga_api' );
73
-
74
- $this->new_install();
75
-
76
- // set db version (Do not increment! See below large comment)
77
- update_option( 'monsterinsights_db_version', '7.4.0' );
78
-
79
- // Remove Yoast hook if present
80
- if ( wp_next_scheduled( 'yst_ga_aggregate_data' ) ) {
81
- wp_clear_scheduled_hook( 'yst_ga_aggregate_data' );
82
- }
83
-
84
- // Clear cache since coming from Yoast
85
- if ( ! $cachec && ! empty( $yoast ) ) {
86
- wp_cache_flush();
87
- $cachec = true;
88
- }
89
- } else { // if existing install
90
- if ( version_compare( $version, '6.0.11', '<' ) ) {
91
- if ( ! $cachec ) {
92
- wp_cache_flush();
93
- $cachec = true;
94
- }
95
- }
96
-
97
- if ( version_compare( $version, '7.0.0', '<' ) ) {
98
- $this->v700_upgrades();
99
- }
100
-
101
- if ( version_compare( $version, '7.4.0', '<' ) ) {
102
- $this->v740_upgrades();
103
- // Do not increment! See below large comment
104
- update_option( 'monsterinsights_db_version', '7.4.0' );
105
- }
106
-
107
- if ( version_compare( $version, '7.5.0', '<' ) ) {
108
- $this->v750_upgrades();
109
- }
110
-
111
- if ( version_compare( $version, '7.6.0', '<' ) ) {
112
- $this->v760_upgrades();
113
- }
114
-
115
- // Do not use. See monsterinsights_after_install_routine comment below.
116
- do_action( 'monsterinsights_after_existing_upgrade_routine', $version );
117
- $version = get_option( 'monsterinsights_current_version', $version );
118
- update_option( 'monsterinsights_version_upgraded_from', $version );
119
- }
120
-
121
- // This hook is used primarily by the Pro version to run some Pro
122
- // specific install stuff. Please do not use this hook. It is not
123
- // considered a public hook by MI's dev team and can/will be removed,
124
- // relocated, and/or altered without warning at any time. You've been warned.
125
- // As this hook is not for public use, we've intentionally not docbloc'd this
126
- // hook to avoid developers seeing it future public dev docs.
127
- do_action( 'monsterinsights_after_install_routine', $version );
128
-
129
- // This is the version of MI installed
130
- update_option( 'monsterinsights_current_version', MONSTERINSIGHTS_VERSION );
131
-
132
- // This is where we save MI settings
133
- update_option( monsterinsights_get_option_name(), $this->new_settings );
134
-
135
- // There's no code for this function below this. Just an explanation
136
- // of the MI core options.
137
-
138
- /**
139
- * Explanation of MonsterInsights core options
140
- *
141
- * By now your head is probably spinning trying to figure
142
- * out what all of these version options are for. Note, I've abbreviated
143
- * "monsterinsights" to "mi" in the options names to make this table easier
144
- * to read.
145
- *
146
- * Here's a basic rundown:
147
- *
148
- * mi_current_version: This starts with the actual version MI was
149
- * installed on. We use this version to
150
- * determine whether or not a site needs
151
- * to run one of the behind the scenes
152
- * MI upgrade routines. This version is updated
153
- * every time a minor or major background upgrade
154
- * routine is run. Generally lags behind the
155
- * MONSTERINSIGHTS_VERSION constant by at most a couple minor
156
- * versions. Never lags behind by 1 major version
157
- * or more generally.
158
- *
159
- * mi_db_version: This is different from mi_current_version.
160
- * Unlike the former, this is used to determine
161
- * if a site needs to run a *user* initiated
162
- * upgrade routine (incremented in MI_Upgrade class). This
163
- * value is only update when a user initiated
164
- * upgrade routine is done. Because we do very
165
- * few user initiated upgrades compared to
166
- * automatic ones, this version can lag behind by
167
- * 2 or even 3 major versions. Generally contains
168
- * the current major version.
169
- *
170
- * mi_settings: Returned by monsterinsights_get_option_name(), this
171
- * is actually "monsterinsights_settings" for both pro
172
- * and lite version. However we use a helper function to
173
- * retrieve the option name in case we ever decide down the
174
- * road to maintain seperate options for the Lite and Pro versions.
175
- * If you need to access MI's settings directly, (as opposed to our
176
- * monsterinsights_get_option helper which uses the option name helper
177
- * automatically), you should use this function to get the
178
- * name of the option to retrieve.
179
- *
180
- * Therefore you should never increment mi_db_version in this file and always increment mi_current_version.
181
- */
182
- }
183
-
184
-
185
- /**
186
- * New MonsterInsights Install routine.
187
- *
188
- * This function installs all of the default
189
- * things on new MI installs. Flight 5476 with
190
- * non-stop service to a whole world of
191
- * possibilities is now boarding.
192
- *
193
- * @since 6.0.0
194
- * @access public
195
- *
196
- * @return void
197
- */
198
- public function new_install() {
199
-
200
- // Add default settings values
201
- $this->new_settings = $this->get_monsterinsights_default_values();
202
-
203
- $this->maybe_import_thirstyaffiliates_options();
204
-
205
- $data = array(
206
- 'installed_version' => MONSTERINSIGHTS_VERSION,
207
- 'installed_date' => time(),
208
- 'installed_pro' => monsterinsights_is_pro_version(),
209
- );
210
-
211
- update_option( 'monsterinsights_over_time', $data );
212
-
213
- // Let addons + MI Pro/Lite hook in here. @todo: doc as nonpublic
214
- do_action( 'monsterinsights_after_new_install_routine', MONSTERINSIGHTS_VERSION );
215
- }
216
-
217
- public function get_monsterinsights_default_values() {
218
- return array(
219
- 'enable_affiliate_links' => true,
220
- 'affiliate_links' => array(
221
- array(
222
- 'path' => '/go/',
223
- 'label' => 'affiliate',
224
- ),
225
- array(
226
- 'path' => '/recommend/',
227
- 'label' => 'affiliate',
228
- )
229
- ),
230
- 'demographics' => 1,
231
- 'ignore_users' => array( 'administrator' ),
232
- 'dashboards_disabled' => 0,
233
- 'anonymize_ips' => 0,
234
- 'extensions_of_files' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
235
- 'subdomain_tracking' => '',
236
- 'link_attribution' => true,
237
- 'tag_links_in_rss' => true,
238
- 'allow_anchor' => 0,
239
- 'add_allow_linker' => 0,
240
- 'custom_code' => '',
241
- 'save_settings' => array( 'administrator' ),
242
- 'view_reports' => array( 'administrator', 'editor' ),
243
- 'events_mode' => 'js',
244
- 'tracking_mode' => 'analytics',
245
- );
246
- }
247
-
248
- /**
249
- * Check if ThirstyAffiliates plugin is installed and use the link prefix value in the affiliate settings.
250
- *
251
- * @return void
252
- */
253
- public function maybe_import_thirstyaffiliates_options() {
254
-
255
- // Check if ThirstyAffiliates is installed.
256
- if ( ! function_exists( 'ThirstyAffiliates' ) ) {
257
- return;
258
- }
259
-
260
- $link_prefix = get_option( 'ta_link_prefix', 'recommends' );
261
-
262
- if ( $link_prefix === 'custom' ) {
263
- $link_prefix = get_option( 'ta_link_prefix_custom', 'recommends' );
264
- }
265
-
266
- if ( ! empty( $link_prefix ) ) {
267
-
268
- // Check if prefix exists.
269
- $prefix_set = false;
270
- foreach ( $this->new_settings['affiliate_links'] as $affiliate_link ) {
271
- if ( $link_prefix === trim( $affiliate_link['path'], '/' ) ) {
272
- $prefix_set = true;
273
- break;
274
- }
275
- }
276
-
277
- if ( ! $prefix_set ) {
278
- $this->new_settings['affiliate_links'][] = array(
279
- 'path' => '/' . $link_prefix . '/',
280
- 'label' => 'affiliate',
281
- );
282
- }
283
- }
284
- }
285
-
286
- /**
287
- * MonsterInsights Version 7.0 upgrades.
288
- *
289
- * This function does the
290
- * upgrade routine from MonsterInsights 6.2->7.0.
291
- *
292
- * @since 7.0.0
293
- * @access public
294
- *
295
- * @return void
296
- */
297
- public function v700_upgrades() {
298
- // 1. Default all event tracking and tracking to GA + JS respectively
299
- // 3a Set tracking_mode to use analytics.js
300
- $this->new_settings['tracking_mode' ] = 'analytics';
301
-
302
-
303
- // 3b Set events mode to use JS if the events mode is not set explicitly to none
304
- if ( empty( $this->new_settings['events_mode' ] ) || $this->new_settings['events_mode' ] !== 'none' ) {
305
- $this->new_settings['events_mode' ] = 'js';
306
- }
307
-
308
- // 2. Migrate manual UA codes
309
- // 2a Manual UA has the lowest priority
310
- if ( ! empty( $this->new_settings['manual_ua_code' ] ) ) {
311
- // Set as manual UA code
312
- is_network_admin() ? update_site_option( 'monsterinsights_network_profile', array( 'manual' => $this->new_settings['manual_ua_code' ] ) ) : update_option( 'monsterinsights_site_profile', array( 'manual' => $this->new_settings['manual_ua_code' ] ) );
313
- }
314
-
315
- // 2b Then try the oAuth UA code
316
- if ( ! empty( $this->new_settings['analytics_profile_code' ] ) ) {
317
- // Set as manual UA code
318
- is_network_admin() ? update_site_option( 'monsterinsights_network_profile', array( 'manual' => $this->new_settings['analytics_profile_code' ] ) ) : update_option( 'monsterinsights_site_profile', array( 'manual' => $this->new_settings['analytics_profile_code' ] ) );
319
- }
320
-
321
- // 3. Migrate License keys
322
- if ( is_multisite() ) {
323
- $ms_license = get_site_option( 'monsterinsights_license', '' );
324
- if ( $ms_license ) {
325
- update_site_option( 'monsterinsights_network_license_updates', get_site_option( 'monsterinsights_license_updates', '' ) );
326
- update_site_option( 'monsterinsights_network_license', $ms_license );
327
- }
328
- }
329
- }
330
-
331
- /**
332
- * Upgrade routine for the new settings panel, onboarding wizard, and the internal-as-outbound v2 settings system.
333
- */
334
- public function v740_upgrades() {
335
-
336
- // 1. Settings Conversions:
337
- // Convert affiliate field to repeater format
338
- if ( ! empty( $this->new_settings['track_internal_as_outbound'] ) ) {
339
- $affiliate_old_paths = $this->new_settings['track_internal_as_outbound'];
340
- $affiliate_old_label = isset( $this->new_settings['track_internal_as_label'] ) ? $this->new_settings['track_internal_as_label'] : '';
341
-
342
- $new_paths = explode( ',', $affiliate_old_paths );
343
-
344
- $this->new_settings['affiliate_links'] = array();
345
- if ( ! empty( $new_paths ) ) {
346
- $this->new_settings['enable_affiliate_links'] = true;
347
- foreach ( $new_paths as $new_path ) {
348
- $this->new_settings['affiliate_links'][] = array(
349
- 'path' => $new_path,
350
- 'label' => $affiliate_old_label,
351
- );
352
- }
353
- }
354
-
355
- $settings = array(
356
- 'track_internal_as_outbound',
357
- 'track_internal_as_label',
358
- );
359
- foreach ( $settings as $setting ) {
360
- if ( ! empty( $this->new_settings[ $setting ] ) ) {
361
- unset( $this->new_settings[ $setting ] );
362
- }
363
- }
364
- }
365
-
366
- // Update option to disable just reports or also the dashboard widget.
367
- if ( isset( $this->new_settings['dashboards_disabled'] ) && $this->new_settings['dashboards_disabled'] ) {
368
- $this->new_settings['dashboards_disabled'] = 'disabled';
369
- }
370
-
371
- $this->new_settings['tracking_mode'] = 'analytics';
372
- $this->new_settings['events_mode'] = 'js';
373
-
374
- // If opted in during allow_tracking era, move that over
375
- if ( ! empty( $this->new_settings['allow_tracking'] ) ) {
376
- $this->new_settings['anonymous_data'] = 1;
377
- }
378
-
379
- // 2. Remove Yoast stuff
380
- delete_option( 'yoast-ga-access_token' );
381
- delete_option( 'yoast-ga-refresh_token' );
382
- delete_option( 'yst_ga' );
383
- delete_option( 'yst_ga_api' );
384
-
385
-
386
- // 3. Remove fake settings from other plugins using our key for some reason and old settings of ours
387
- $settings = array(
388
- 'debug_mode',
389
- 'track_download_as',
390
- 'analytics_profile',
391
- 'analytics_profile_code',
392
- 'analytics_profile_name',
393
- 'manual_ua_code',
394
- 'track_outbound',
395
- 'track_download_as',
396
- 'enhanced_link_attribution',
397
- 'oauth_version',
398
- 'monsterinsights_oauth_status',
399
- 'firebug_lite',
400
- 'google_auth_code',
401
- 'allow_tracking',
402
- );
403
-
404
- foreach ( $settings as $setting ) {
405
- if ( ! empty( $this->new_settings[ $setting ] ) ) {
406
- unset( $this->new_settings[ $setting ] );
407
- }
408
- }
409
-
410
- $settings = array(
411
- '_repeated',
412
- 'ajax',
413
- 'asmselect0',
414
- 'bawac_force_nonce',
415
- 'icl_post_language',
416
- 'saved_values',
417
- 'mlcf_email',
418
- 'mlcf_name',
419
- 'cron_failed',
420
- 'undefined',
421
- 'cf_email',
422
- 'cf_message',
423
- 'cf_name',
424
- 'cf_number',
425
- 'cf_phone',
426
- 'cf_subject',
427
- 'content',
428
- 'credentials',
429
- 'cron_failed',
430
- 'cron_last_run',
431
- 'global-css',
432
- 'grids',
433
- 'page',
434
- 'punch-fonts',
435
- 'return_tab',
436
- 'skins',
437
- 'navigation-skins',
438
- 'title',
439
- 'type',
440
- 'wpcf_email',
441
- 'wpcf_your_name',
442
- );
443
-
444
- foreach ( $settings as $setting ) {
445
- if ( ! empty( $this->new_settings[ $setting ] ) ) {
446
- unset( $this->new_settings[ $setting ] );
447
- }
448
- }
449
-
450
- // 4. Remove old crons
451
- if ( wp_next_scheduled( 'monsterinsights_daily_cron' ) ) {
452
- wp_clear_scheduled_hook( 'monsterinsights_daily_cron' );
453
- }
454
- if ( wp_next_scheduled( 'monsterinsights_send_tracking_data' ) ) {
455
- wp_clear_scheduled_hook( 'monsterinsights_send_tracking_data' );
456
- }
457
-
458
- if ( wp_next_scheduled( 'monsterinsights_send_tracking_checkin' ) ) {
459
- wp_clear_scheduled_hook( 'monsterinsights_send_tracking_checkin' );
460
- }
461
-
462
- if ( wp_next_scheduled( 'monsterinsights_weekly_cron' ) ) {
463
- wp_clear_scheduled_hook( 'monsterinsights_weekly_cron' );
464
- }
465
-
466
- if ( wp_next_scheduled( 'yst_ga_aggregate_data' ) ) {
467
- wp_clear_scheduled_hook( 'yst_ga_aggregate_data' );
468
- }
469
-
470
- delete_option( 'monsterinsights_tracking_last_send' );
471
- delete_option( 'mi_tracking_last_send' );
472
-
473
- // 5. Remove old option
474
- delete_option( 'monsterinsights_settings_version' );
475
- }
476
-
477
-
478
- /**
479
- * Upgrade routine
480
- */
481
- public function v750_upgrades() {
482
- // 1. One time re-prompt for anonymous data (due to migration bug now fixed)
483
- // if ( ! monsterinsights_is_pro_version() ) {
484
- // if ( empty( $this->new_settings[ 'anonymous_data' ] ) ) {
485
- // update_option( 'monsterinsights_tracking_notice', 0 );
486
- // }
487
- // }
488
- //
489
- // 2. Clear old settings ( 'tracking_mode','events_mode',)
490
-
491
-
492
- // 3. Attempt to extract the cross-domain settings from the Custom Code area and use in the new option.
493
- $custom_code = isset( $this->new_settings['custom_code'] ) ? $this->new_settings['custom_code'] : '';
494
- if ( ! empty( $custom_code ) ) {
495
- $pattern = '/(?:\'linker:autoLink\', )(?:\[)(.*)(?:\])/m';
496
- preg_match_all( $pattern, $custom_code, $matches, PREG_SET_ORDER, 0 );
497
- if ( ! empty( $matches ) && isset( $matches[0] ) && isset( $matches[0][1] ) ) {
498
- $cross_domains = array();
499
- $domains = explode( ',', $matches[0][1] );
500
- foreach ( $domains as $key => $domain ) {
501
- $domain = trim( $domain );
502
- $cross_domains[] = array(
503
- 'domain' => trim( $domain, '\'\"' ),
504
- );
505
- }
506
- $this->new_settings['add_allow_linker'] = true;
507
- $this->new_settings['cross_domains'] = $cross_domains;
508
-
509
- $notices = get_option( 'monsterinsights_notices' );
510
- if ( ! is_array( $notices ) ) {
511
- $notices = array();
512
- }
513
- $notices['monsterinsights_cross_domains_extracted'] = false;
514
- update_option( 'monsterinsights_notices', $notices );
515
- }
516
- }
517
- }
518
-
519
- /**
520
- * Upgrade routine for version 7.6.0
521
- */
522
- public function v760_upgrades() {
523
-
524
- $cross_domains = isset( $this->new_settings['cross_domains'] ) ? $this->new_settings['cross_domains'] : array();
525
-
526
- if ( ! empty( $cross_domains ) && is_array( $cross_domains ) ) {
527
- $current_domain = wp_parse_url( home_url() );
528
- $current_domain = isset( $current_domain['host'] ) ? $current_domain['host'] : '';
529
- if ( ! empty( $current_domain ) ) {
530
- $regex = '/^(?:' . $current_domain . '|(?:.+)\.' . $current_domain . ')$/m';
531
- foreach ( $cross_domains as $key => $cross_domain ) {
532
- if ( ! isset( $cross_domain['domain'] ) ) {
533
- continue;
534
- }
535
- preg_match( $regex, $cross_domain['domain'], $matches );
536
- if ( count( $matches ) > 0 ) {
537
- unset( $this->new_settings['cross_domains'][ $key ] );
538
- }
539
- }
540
- }
541
- }
542
-
543
- }
544
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MonsterInsights Installation and Automatic Upgrades.
4
+ *
5
+ * This file handles setting up new
6
+ * MonsterInsights installs as well as performing
7
+ * behind the scene upgrades between
8
+ * MonsterInsights versions.
9
+ *
10
+ * @package MonsterInsights
11
+ * @subpackage Install/Upgrade
12
+ * @since 6.0.0
13
+ */
14
+
15
+ // Exit if accessed directly
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+ /**
21
+ * MonsterInsights Install.
22
+ *
23
+ * This class handles a new MI install
24
+ * as well as automatic (non-user initiated)
25
+ * upgrade routines.
26
+ *
27
+ * @since 6.0.0
28
+ * @access public
29
+ */
30
+ class MonsterInsights_Install {
31
+
32
+ /**
33
+ * MI Settings.
34
+ *
35
+ * @since 6.0.0
36
+ * @access public
37
+ * @var array $new_settings When the init() function starts, initially
38
+ * contains the original settings. At the end
39
+ * of init() contains the settings to save.
40
+ */
41
+ public $new_settings = array();
42
+
43
+ /**
44
+ * Install/Upgrade routine.
45
+ *
46
+ * This function is what is called to actually install MI data on new installs and to do
47
+ * behind the scenes upgrades on MI upgrades. If this function contains a bug, the results
48
+ * can be catastrophic. This function gets the highest priority in all of MI for unit tests.
49
+ *
50
+ * @since 6.0.0
51
+ * @access public
52
+ *
53
+ * @return void
54
+ */
55
+ public function init() {
56
+
57
+ // Get a copy of the current MI settings.
58
+ $this->new_settings = get_option( monsterinsights_get_option_name() );
59
+
60
+ $version = get_option( 'monsterinsights_current_version', false );
61
+ $cachec = false; // have we forced an object cache to be cleared already (so we don't clear it unnecessarily)
62
+
63
+ // if new install or Yoast Era instal
64
+ if ( ! $version ) {
65
+ // See if from Yoast
66
+ $yoast = get_option( 'yst_ga', false );
67
+
68
+ // In case from Yoast, start from scratch
69
+ delete_option( 'yoast-ga-access_token' );
70
+ delete_option( 'yoast-ga-refresh_token' );
71
+ delete_option( 'yst_ga' );
72
+ delete_option( 'yst_ga_api' );
73
+
74
+ $this->new_install();
75
+
76
+ // set db version (Do not increment! See below large comment)
77
+ update_option( 'monsterinsights_db_version', '7.4.0' );
78
+
79
+ // Remove Yoast hook if present
80
+ if ( wp_next_scheduled( 'yst_ga_aggregate_data' ) ) {
81
+ wp_clear_scheduled_hook( 'yst_ga_aggregate_data' );
82
+ }
83
+
84
+ // Clear cache since coming from Yoast
85
+ if ( ! $cachec && ! empty( $yoast ) ) {
86
+ wp_cache_flush();
87
+ $cachec = true;
88
+ }
89
+ } else { // if existing install
90
+ if ( version_compare( $version, '6.0.11', '<' ) ) {
91
+ if ( ! $cachec ) {
92
+ wp_cache_flush();
93
+ $cachec = true;
94
+ }
95
+ }
96
+
97
+ if ( version_compare( $version, '7.0.0', '<' ) ) {
98
+ $this->v700_upgrades();
99
+ }
100
+
101
+ if ( version_compare( $version, '7.4.0', '<' ) ) {
102
+ $this->v740_upgrades();
103
+ // Do not increment! See below large comment
104
+ update_option( 'monsterinsights_db_version', '7.4.0' );
105
+ }
106
+
107
+ if ( version_compare( $version, '7.5.0', '<' ) ) {
108
+ $this->v750_upgrades();
109
+ }
110
+
111
+ if ( version_compare( $version, '7.6.0', '<' ) ) {
112
+ $this->v760_upgrades();
113
+ }
114
+
115
+ if ( version_compare( $version, '7.7.1', '<' ) ) {
116
+ $this->v771_upgrades();
117
+ }
118
+
119
+ if ( version_compare( $version, '7.8.0', '<' ) ) {
120
+ $this->v780_upgrades();
121
+ }
122
+
123
+ // Do not use. See monsterinsights_after_install_routine comment below.
124
+ do_action( 'monsterinsights_after_existing_upgrade_routine', $version );
125
+ $version = get_option( 'monsterinsights_current_version', $version );
126
+ update_option( 'monsterinsights_version_upgraded_from', $version );
127
+ }
128
+
129
+ // This hook is used primarily by the Pro version to run some Pro
130
+ // specific install stuff. Please do not use this hook. It is not
131
+ // considered a public hook by MI's dev team and can/will be removed,
132
+ // relocated, and/or altered without warning at any time. You've been warned.
133
+ // As this hook is not for public use, we've intentionally not docbloc'd this
134
+ // hook to avoid developers seeing it future public dev docs.
135
+ do_action( 'monsterinsights_after_install_routine', $version );
136
+
137
+ // This is the version of MI installed
138
+ update_option( 'monsterinsights_current_version', MONSTERINSIGHTS_VERSION );
139
+
140
+ // This is where we save MI settings
141
+ update_option( monsterinsights_get_option_name(), $this->new_settings );
142
+
143
+ // There's no code for this function below this. Just an explanation
144
+ // of the MI core options.
145
+
146
+ /**
147
+ * Explanation of MonsterInsights core options
148
+ *
149
+ * By now your head is probably spinning trying to figure
150
+ * out what all of these version options are for. Note, I've abbreviated
151
+ * "monsterinsights" to "mi" in the options names to make this table easier
152
+ * to read.
153
+ *
154
+ * Here's a basic rundown:
155
+ *
156
+ * mi_current_version: This starts with the actual version MI was
157
+ * installed on. We use this version to
158
+ * determine whether or not a site needs
159
+ * to run one of the behind the scenes
160
+ * MI upgrade routines. This version is updated
161
+ * every time a minor or major background upgrade
162
+ * routine is run. Generally lags behind the
163
+ * MONSTERINSIGHTS_VERSION constant by at most a couple minor
164
+ * versions. Never lags behind by 1 major version
165
+ * or more generally.
166
+ *
167
+ * mi_db_version: This is different from mi_current_version.
168
+ * Unlike the former, this is used to determine
169
+ * if a site needs to run a *user* initiated
170
+ * upgrade routine (incremented in MI_Upgrade class). This
171
+ * value is only update when a user initiated
172
+ * upgrade routine is done. Because we do very
173
+ * few user initiated upgrades compared to
174
+ * automatic ones, this version can lag behind by
175
+ * 2 or even 3 major versions. Generally contains
176
+ * the current major version.
177
+ *
178
+ * mi_settings: Returned by monsterinsights_get_option_name(), this
179
+ * is actually "monsterinsights_settings" for both pro
180
+ * and lite version. However we use a helper function to
181
+ * retrieve the option name in case we ever decide down the
182
+ * road to maintain seperate options for the Lite and Pro versions.
183
+ * If you need to access MI's settings directly, (as opposed to our
184
+ * monsterinsights_get_option helper which uses the option name helper
185
+ * automatically), you should use this function to get the
186
+ * name of the option to retrieve.
187
+ *
188
+ * Therefore you should never increment mi_db_version in this file and always increment mi_current_version.
189
+ */
190
+ }
191
+
192
+
193
+ /**
194
+ * New MonsterInsights Install routine.
195
+ *
196
+ * This function installs all of the default
197
+ * things on new MI installs. Flight 5476 with
198
+ * non-stop service to a whole world of
199
+ * possibilities is now boarding.
200
+ *
201
+ * @since 6.0.0
202
+ * @access public
203
+ *
204
+ * @return void
205
+ */
206
+ public function new_install() {
207
+
208
+ // Add default settings values
209
+ $this->new_settings = $this->get_monsterinsights_default_values();
210
+
211
+ $this->maybe_import_thirstyaffiliates_options();
212
+
213
+ $data = array(
214
+ 'installed_version' => MONSTERINSIGHTS_VERSION,
215
+ 'installed_date' => time(),
216
+ 'installed_pro' => monsterinsights_is_pro_version(),
217
+ );
218
+
219
+ update_option( 'monsterinsights_over_time', $data );
220
+
221
+ // Let addons + MI Pro/Lite hook in here. @todo: doc as nonpublic
222
+ do_action( 'monsterinsights_after_new_install_routine', MONSTERINSIGHTS_VERSION );
223
+ }
224
+
225
+ public function get_monsterinsights_default_values() {
226
+ return array(
227
+ 'enable_affiliate_links' => true,
228
+ 'affiliate_links' => array(
229
+ array(
230
+ 'path' => '/go/',
231
+ 'label' => 'affiliate',
232
+ ),
233
+ array(
234
+ 'path' => '/recommend/',
235
+ 'label' => 'affiliate',
236
+ )
237
+ ),
238
+ 'demographics' => 1,
239
+ 'ignore_users' => array( 'administrator' ),
240
+ 'dashboards_disabled' => 0,
241
+ 'anonymize_ips' => 0,
242
+ 'extensions_of_files' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
243
+ 'subdomain_tracking' => '',
244
+ 'link_attribution' => true,
245
+ 'tag_links_in_rss' => true,
246
+ 'allow_anchor' => 0,
247
+ 'add_allow_linker' => 0,
248
+ 'custom_code' => '',
249
+ 'save_settings' => array( 'administrator' ),
250
+ 'view_reports' => array( 'administrator', 'editor' ),
251
+ 'events_mode' => 'js',
252
+ 'tracking_mode' => 'analytics',
253
+ );
254
+ }
255
+
256
+ /**
257
+ * Check if ThirstyAffiliates plugin is installed and use the link prefix value in the affiliate settings.
258
+ *
259
+ * @return void
260
+ */
261
+ public function maybe_import_thirstyaffiliates_options() {
262
+
263
+ // Check if ThirstyAffiliates is installed.
264
+ if ( ! function_exists( 'ThirstyAffiliates' ) ) {
265
+ return;
266
+ }
267
+
268
+ $link_prefix = get_option( 'ta_link_prefix', 'recommends' );
269
+
270
+ if ( $link_prefix === 'custom' ) {
271
+ $link_prefix = get_option( 'ta_link_prefix_custom', 'recommends' );
272
+ }
273
+
274
+ if ( ! empty( $link_prefix ) ) {
275
+
276
+ // Check if prefix exists.
277
+ $prefix_set = false;
278
+ foreach ( $this->new_settings['affiliate_links'] as $affiliate_link ) {
279
+ if ( $link_prefix === trim( $affiliate_link['path'], '/' ) ) {
280
+ $prefix_set = true;
281
+ break;
282
+ }
283
+ }
284
+
285
+ if ( ! $prefix_set ) {
286
+ $this->new_settings['affiliate_links'][] = array(
287
+ 'path' => '/' . $link_prefix . '/',
288
+ 'label' => 'affiliate',
289
+ );
290
+ }
291
+ }
292
+ }
293
+
294
+ /**
295
+ * MonsterInsights Version 7.0 upgrades.
296
+ *
297
+ * This function does the
298
+ * upgrade routine from MonsterInsights 6.2->7.0.
299
+ *
300
+ * @since 7.0.0
301
+ * @access public
302
+ *
303
+ * @return void
304
+ */
305
+ public function v700_upgrades() {
306
+ // 1. Default all event tracking and tracking to GA + JS respectively
307
+ // 3a Set tracking_mode to use analytics.js
308
+ $this->new_settings['tracking_mode' ] = 'analytics';
309
+
310
+
311
+ // 3b Set events mode to use JS if the events mode is not set explicitly to none
312
+ if ( empty( $this->new_settings['events_mode' ] ) || $this->new_settings['events_mode' ] !== 'none' ) {
313
+ $this->new_settings['events_mode' ] = 'js';
314
+ }
315
+
316
+ // 2. Migrate manual UA codes
317
+ // 2a Manual UA has the lowest priority
318
+ if ( ! empty( $this->new_settings['manual_ua_code' ] ) ) {
319
+ // Set as manual UA code
320
+ is_network_admin() ? update_site_option( 'monsterinsights_network_profile', array( 'manual' => $this->new_settings['manual_ua_code' ] ) ) : update_option( 'monsterinsights_site_profile', array( 'manual' => $this->new_settings['manual_ua_code' ] ) );
321
+ }
322
+
323
+ // 2b Then try the oAuth UA code
324
+ if ( ! empty( $this->new_settings['analytics_profile_code' ] ) ) {
325
+ // Set as manual UA code
326
+ is_network_admin() ? update_site_option( 'monsterinsights_network_profile', array( 'manual' => $this->new_settings['analytics_profile_code' ] ) ) : update_option( 'monsterinsights_site_profile', array( 'manual' => $this->new_settings['analytics_profile_code' ] ) );
327
+ }
328
+
329
+ // 3. Migrate License keys
330
+ if ( is_multisite() ) {
331
+ $ms_license = get_site_option( 'monsterinsights_license', '' );
332
+ if ( $ms_license ) {
333
+ update_site_option( 'monsterinsights_network_license_updates', get_site_option( 'monsterinsights_license_updates', '' ) );
334
+ update_site_option( 'monsterinsights_network_license', $ms_license );
335
+ }
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Upgrade routine for the new settings panel, onboarding wizard, and the internal-as-outbound v2 settings system.
341
+ */
342
+ public function v740_upgrades() {
343
+
344
+ // 1. Settings Conversions:
345
+ // Convert affiliate field to repeater format
346
+ if ( ! empty( $this->new_settings['track_internal_as_outbound'] ) ) {
347
+ $affiliate_old_paths = $this->new_settings['track_internal_as_outbound'];
348
+ $affiliate_old_label = isset( $this->new_settings['track_internal_as_label'] ) ? $this->new_settings['track_internal_as_label'] : '';
349
+
350
+ $new_paths = explode( ',', $affiliate_old_paths );
351
+
352
+ $this->new_settings['affiliate_links'] = array();
353
+ if ( ! empty( $new_paths ) ) {
354
+ $this->new_settings['enable_affiliate_links'] = true;
355
+ foreach ( $new_paths as $new_path ) {
356
+ $this->new_settings['affiliate_links'][] = array(
357
+ 'path' => $new_path,
358
+ 'label' => $affiliate_old_label,
359
+ );
360
+ }
361
+ }
362
+
363
+ $settings = array(
364
+ 'track_internal_as_outbound',
365
+ 'track_internal_as_label',
366
+ );
367
+ foreach ( $settings as $setting ) {
368
+ if ( ! empty( $this->new_settings[ $setting ] ) ) {
369
+ unset( $this->new_settings[ $setting ] );
370
+ }
371
+ }
372
+ }
373
+
374
+ // Update option to disable just reports or also the dashboard widget.
375
+ if ( isset( $this->new_settings['dashboards_disabled'] ) && $this->new_settings['dashboards_disabled'] ) {
376
+ $this->new_settings['dashboards_disabled'] = 'disabled';
377
+ }
378
+
379
+ $this->new_settings['tracking_mode'] = 'analytics';
380
+ $this->new_settings['events_mode'] = 'js';
381
+
382
+ // If opted in during allow_tracking era, move that over
383
+ if ( ! empty( $this->new_settings['allow_tracking'] ) ) {
384
+ $this->new_settings['anonymous_data'] = 1;
385
+ }
386
+
387
+ // 2. Remove Yoast stuff
388
+ delete_option( 'yoast-ga-access_token' );
389
+ delete_option( 'yoast-ga-refresh_token' );
390
+ delete_option( 'yst_ga' );
391
+ delete_option( 'yst_ga_api' );
392
+
393
+
394
+ // 3. Remove fake settings from other plugins using our key for some reason and old settings of ours
395
+ $settings = array(
396
+ 'debug_mode',
397
+ 'track_download_as',
398
+ 'analytics_profile',
399
+ 'analytics_profile_code',
400
+ 'analytics_profile_name',
401
+ 'manual_ua_code',
402
+ 'track_outbound',
403
+ 'track_download_as',
404
+ 'enhanced_link_attribution',
405
+ 'oauth_version',
406
+ 'monsterinsights_oauth_status',
407
+ 'firebug_lite',
408
+ 'google_auth_code',
409
+ 'allow_tracking',
410
+ );
411
+
412
+ foreach ( $settings as $setting ) {
413
+ if ( ! empty( $this->new_settings[ $setting ] ) ) {
414
+ unset( $this->new_settings[ $setting ] );
415
+ }
416
+ }
417
+
418
+ $settings = array(
419
+ '_repeated',
420
+ 'ajax',
421
+ 'asmselect0',
422
+ 'bawac_force_nonce',
423
+ 'icl_post_language',
424
+ 'saved_values',
425
+ 'mlcf_email',
426
+ 'mlcf_name',
427
+ 'cron_failed',
428
+ 'undefined',
429
+ 'cf_email',
430
+ 'cf_message',
431
+ 'cf_name',
432
+ 'cf_number',
433
+ 'cf_phone',
434
+ 'cf_subject',
435
+ 'content',
436
+ 'credentials',
437
+ 'cron_failed',
438
+ 'cron_last_run',
439
+ 'global-css',
440
+ 'grids',
441
+ 'page',
442
+ 'punch-fonts',
443
+ 'return_tab',
444
+ 'skins',
445
+ 'navigation-skins',
446
+ 'title',
447
+ 'type',
448
+ 'wpcf_email',
449
+ 'wpcf_your_name',
450
+ );
451
+
452
+ foreach ( $settings as $setting ) {
453
+ if ( ! empty( $this->new_settings[ $setting ] ) ) {
454
+ unset( $this->new_settings[ $setting ] );
455
+ }
456
+ }
457
+
458
+ // 4. Remove old crons
459
+ if ( wp_next_scheduled( 'monsterinsights_daily_cron' ) ) {
460
+ wp_clear_scheduled_hook( 'monsterinsights_daily_cron' );
461
+ }
462
+ if ( wp_next_scheduled( 'monsterinsights_send_tracking_data' ) ) {
463
+ wp_clear_scheduled_hook( 'monsterinsights_send_tracking_data' );
464
+ }
465
+
466
+ if ( wp_next_scheduled( 'monsterinsights_send_tracking_checkin' ) ) {
467
+ wp_clear_scheduled_hook( 'monsterinsights_send_tracking_checkin' );
468
+ }
469
+
470
+ if ( wp_next_scheduled( 'monsterinsights_weekly_cron' ) ) {
471
+ wp_clear_scheduled_hook( 'monsterinsights_weekly_cron' );
472
+ }
473
+
474
+ if ( wp_next_scheduled( 'yst_ga_aggregate_data' ) ) {
475
+ wp_clear_scheduled_hook( 'yst_ga_aggregate_data' );
476
+ }
477
+
478
+ delete_option( 'monsterinsights_tracking_last_send' );
479
+ delete_option( 'mi_tracking_last_send' );
480
+
481
+ // 5. Remove old option
482
+ delete_option( 'monsterinsights_settings_version' );
483
+ }
484
+
485
+
486
+ /**
487
+ * Upgrade routine
488
+ */
489
+ public function v750_upgrades() {
490
+ // 1. One time re-prompt for anonymous data (due to migration bug now fixed)
491
+ // if ( ! monsterinsights_is_pro_version() ) {
492
+ // if ( empty( $this->new_settings[ 'anonymous_data' ] ) ) {
493
+ // update_option( 'monsterinsights_tracking_notice', 0 );
494
+ // }
495
+ // }
496
+ //
497
+ // 2. Clear old settings ( 'tracking_mode','events_mode',)
498
+
499
+
500
+ // 3. Attempt to extract the cross-domain settings from the Custom Code area and use in the new option.
501
+ $custom_code = isset( $this->new_settings['custom_code'] ) ? $this->new_settings['custom_code'] : '';
502
+ if ( ! empty( $custom_code ) ) {
503
+ $pattern = '/(?:\'linker:autoLink\', )(?:\[)(.*)(?:\])/m';
504
+ preg_match_all( $pattern, $custom_code, $matches, PREG_SET_ORDER, 0 );
505
+ if ( ! empty( $matches ) && isset( $matches[0] ) && isset( $matches[0][1] ) ) {
506
+ $cross_domains = array();
507
+ $domains = explode( ',', $matches[0][1] );
508
+ foreach ( $domains as $key => $domain ) {
509
+ $domain = trim( $domain );
510
+ $cross_domains[] = array(
511
+ 'domain' => trim( $domain, '\'\"' ),
512
+ );
513
+ }
514
+ $this->new_settings['add_allow_linker'] = true;
515
+ $this->new_settings['cross_domains'] = $cross_domains;
516
+
517
+ $notices = get_option( 'monsterinsights_notices' );
518
+ if ( ! is_array( $notices ) ) {
519
+ $notices = array();
520
+ }
521
+ $notices['monsterinsights_cross_domains_extracted'] = false;
522
+ update_option( 'monsterinsights_notices', $notices );
523
+ }
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Upgrade routine for version 7.6.0
529
+ */
530
+ public function v760_upgrades() {
531
+
532
+ $cross_domains = isset( $this->new_settings['cross_domains'] ) ? $this->new_settings['cross_domains'] : array();
533
+
534
+ if ( ! empty( $cross_domains ) && is_array( $cross_domains ) ) {
535
+ $current_domain = wp_parse_url( home_url() );
536
+ $current_domain = isset( $current_domain['host'] ) ? $current_domain['host'] : '';
537
+ if ( ! empty( $current_domain ) ) {
538
+ $regex = '/^(?:' . $current_domain . '|(?:.+)\.' . $current_domain . ')$/m';
539
+ foreach ( $cross_domains as $key => $cross_domain ) {
540
+ if ( ! isset( $cross_domain['domain'] ) ) {
541
+ continue;
542
+ }
543
+ preg_match( $regex, $cross_domain['domain'], $matches );
544
+ if ( count( $matches ) > 0 ) {
545
+ unset( $this->new_settings['cross_domains'][ $key ] );
546
+ }
547
+ }
548
+ }
549
+ }
550
+
551
+ }
552
+
553
+ /**
554
+ * Upgrade routine for version 7.7.1
555
+ */
556
+ public function v771_upgrades() {
557
+
558
+ if ( ! monsterinsights_is_pro_version() ) {
559
+ // We only need to run this for the Pro version.
560
+ return;
561
+ }
562
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
563
+
564
+ $plugin = 'wp-scroll-depth/wp-scroll-depth.php';
565
+ // Check if wp-scroll-depth is active and deactivate to avoid conflicts with the pro scroll tracking feature.
566
+ if ( is_plugin_active( $plugin ) ) {
567
+ deactivate_plugins( $plugin );
568
+ }
569
+
570
+ }
571
+
572
+ /**
573
+ * Upgrade routine for version 7.7.2
574
+ */
575
+ public function v780_upgrades() {
576
+
577
+ if ( monsterinsights_get_ua() ) {
578
+ // If we have a UA, don't show the first run notice.
579
+ monsterinsights_update_option( 'monsterinsights_first_run_notice', true );
580
+
581
+ // If they are already tracking when they upgrade, mark connected time as now.
582
+ $over_time = get_option( 'monsterinsights_over_time', array() );
583
+ if ( empty( $over_time['connected_date'] ) ) {
584
+ $over_time['connected_date'] = time();
585
+ update_option( 'monsterinsights_over_time', $over_time );
586
+ }
587
+ }
588
+
589
+ }
590
+ }
includes/license.php DELETED
@@ -1,400 +0,0 @@
1
- <?php
2
- /**
3
- * License class.
4
- *
5
- * Helper for licenses.
6
- *
7
- * @since 7.0.0
8
- *
9
- * @package MonsterInsights
10
- * @subpackage License
11
- * @author Chris Christoff
12
- */
13
-
14
- // Exit if accessed directly
15
- if ( ! defined( 'ABSPATH' ) ) {
16
- exit;
17
- }
18
-
19
- final class MonsterInsights_License {
20
-
21
- private $site = array();
22
- private $network = array();
23
- private $licensed = false;
24
- private $using_nl = false;
25
-
26
- /**
27
- * Primary class constructor.
28
- *
29
- * @access public
30
- * @since 7.0.0
31
- */
32
- public function __construct() {
33
- $this->site = $this->get_site_license();
34
- $this->network = $this->get_network_license();
35
- $this->license_to_use();
36
- }
37
-
38
- private function license_to_use() {
39
- if ( is_network_admin() ) {
40
- $license = $this->get_network_license_key();
41
- if ( ! empty( $license ) ) {
42
- $this->licensed = true;
43
- $this->using_nl = true;
44
- }
45
- } else {
46
- $license = $this->get_site_license_key();
47
- if ( ! empty( $license ) ) {
48
- $this->licensed = true;
49
- $this->using_nl = false;
50
- } else {
51
- $license = $this->get_network_license_key();
52
- if ( ! empty( $license ) ) {
53
- $this->licensed = true;
54
- $this->using_nl = true;
55
- }
56
- }
57
- }
58
- }
59
-
60
- public function using_network_license() {
61
- return $this->using_nl;
62
- }
63
-
64
- public function get_site_license( $force = false ) {
65
- if ( ! empty( $this->site ) && ! $force ) {
66
- return $this->site;
67
- } else {
68
- $site = get_option( 'monsterinsights_license', array() );
69
- $this->site = $site;
70
- return $site;
71
- }
72
- }
73
-
74
- public function get_network_license( $force = false ) {
75
- if ( ! empty( $this->network ) && ! $force ) {
76
- return $this->network;
77
- } else {
78
- $network = get_site_option( 'monsterinsights_network_license', array() );
79
- $this->network = $network;
80
- return $network;
81
- }
82
- }
83
-
84
- public function get_license_key() {
85
- $license_key = MonsterInsights()->license->get_site_license_key();
86
- $license_key = ! empty( $license_key ) ? $license_key : MonsterInsights()->license->get_network_license_key();
87
- $license_key = ! empty( $license_key ) ? $license_key : MonsterInsights()->license->get_default_license_key();
88
- return $license_key;
89
- }
90
- public function get_site_license_key(){
91
- return ( ! empty( $this->site['key'] ) && is_string( $this->site['key'] ) && strlen( $this->site['key'] ) > 10 ) ? $this->site['key'] : '';
92
- }
93
- public function get_network_license_key(){
94
- return ( ! empty( $this->network['key'] ) && is_string( $this->network['key'] ) && strlen( $this->network['key'] ) > 10 ) ? $this->network['key'] : '';
95
- }
96
-
97
- public function has_license() {
98
- return $this->licensed;
99
- }
100
-
101
- public function is_site_licensed(){
102
- return ! empty( $this->site['key'] ) // has key
103
- && $this->get_site_license_type() // has type
104
- && ! $this->site_license_expired() // isn't expired
105
- && ! $this->site_license_disabled() // isn't disabled
106
- && ! $this->site_license_invalid() // isn't invalid
107
- ;
108
- }
109
-
110
- public function is_network_licensed() {
111
- return ! empty( $this->network['key'] ) // has key
112
- && $this->get_network_license_type() // has type
113
- && ! $this->network_license_expired() // isn't expired
114
- && ! $this->network_license_disabled() // isn't disabled
115
- && ! $this->network_license_invalid() // isn't invalid
116
- ;
117
- }
118
-
119
-
120
- public function get_site_license_updates(){
121
- return get_option( 'monsterinsights_license_updates', '' );
122
- }
123
- public function get_network_license_updates(){
124
- return get_site_option( 'monsterinsights_network_license_updates', '' );
125
- }
126
-
127
- public function set_site_license_updates(){
128
- update_option( 'monsterinsights_license_updates', strtotime( '+8 hours' ) );
129
- }
130
- public function set_network_license_updates() {
131
- update_site_option( 'monsterinsights_network_license_updates', strtotime( '+8 hours' ) );
132
- }
133
-
134
- public function delete_site_license_updates(){
135
- delete_option( 'monsterinsights_license_updates' );
136
- }
137
- public function delete_network_license_updates(){
138
- delete_site_option( 'monsterinsights_license_updates' );
139
- }
140
-
141
- public function time_to_check_site_license(){
142
- $timestamp = get_option( 'monsterinsights_license_updates' );
143
- if ( ! $timestamp ) {
144
- return true;
145
- } else {
146
- $current_timestamp = time();
147
- if ( $current_timestamp < $timestamp ) {
148
- return false;
149
- } else {
150
- return true;
151
- }
152
- }
153
- }
154
- public function time_to_check_network_license(){
155
- $timestamp = get_site_option( 'monsterinsights_network_license_updates' );
156
- if ( ! $timestamp ) {
157
- return true;
158
- } else {
159
- $current_timestamp = time();
160
- if ( $current_timestamp < $timestamp ) {
161
- return false;
162
- } else {
163
- return true;
164
- }
165
- }
166
- }
167
-
168
- public function set_site_license( $data = array() ){
169
- update_option( 'monsterinsights_license', $data );
170
- $this->set_site_license_updates();
171
- $this->site = $data;
172
- }
173
- public function set_network_license( $data = array() ){
174
- update_site_option( 'monsterinsights_network_license', $data );
175
- $this->set_network_license_updates();
176
- $this->network = $data;
177
- }
178
-
179
- public function delete_site_license() {
180
- delete_option( 'monsterinsights_license' );
181
- $this->delete_site_license_updates();
182
- $this->site = array();
183
- }
184
- public function delete_network_license() {
185
- delete_site_option( 'monsterinsights_network_license' );
186
- $this->delete_network_license_updates();
187
- $this->network = array();
188
- }
189
-
190
- public function get_license_type(){
191
- if ( ! $this->has_license() ) {
192
- return false;
193
- }
194
-
195
- return $this->using_network_license() ? $this->get_network_license_type() : $this->get_site_license_type();
196
- }
197
- public function get_site_license_type(){
198
- return ( $this->get_site_license_key() && ! empty( $this->site['type'] ) && $this->is_valid_license_type( $this->site['type'] ) ) ? $this->site['type'] : '';
199
- }
200
- public function get_network_license_type(){
201
- return ( $this->get_network_license_key() && ! empty( $this->network['type'] ) && $this->is_valid_license_type( $this->network['type'] ) ) ? $this->network['type'] : '';
202
- }
203
-
204
- public function license_has_error(){
205
- if ( ! $this->has_license() ) {
206
- return false;
207
- }
208
-
209
- return $this->using_network_license() ? $this->network_license_has_error() : $this->site_license_has_error();
210
- }
211
- public function site_license_has_error() {
212
- return
213
- $this->site_license_expired() // is expired
214
- || $this->site_license_disabled() // is disabled
215
- || $this->site_license_invalid() // is invalid
216
- ;
217
- }
218
- public function network_license_has_error(){
219
- return
220
- $this->network_license_expired() // is expired
221
- || $this->network_license_disabled() // is disabled
222
- || $this->network_license_invalid() // is invalid
223
- ;
224
- }
225
-
226
- public function license_expired(){
227
- if ( ! $this->has_license() ) {
228
- return false;
229
- }
230
-
231
- return $this->using_network_license() ? $this->network_license_expired() : $this->site_license_expired();
232
- }
233
- public function site_license_expired(){
234
- return ! empty( $this->site['is_expired'] );
235
- }
236
- public function network_license_expired(){
237
- return ! empty( $this->network['is_expired'] );
238
- }
239
-
240
- public function license_disabled(){
241
- if ( ! $this->has_license() ) {
242
- return false;
243
- }
244
-
245
- return $this->using_network_license() ? $this->network_license_disabled() : $this->site_license_disabled();
246
- }
247
- public function site_license_disabled() {
248
- return ! empty( $this->site['is_disabled'] );
249
- }
250
- public function network_license_disabled(){
251
- return ! empty( $this->network['is_disabled'] );
252
- }
253
-
254
- public function license_invalid(){
255
- if ( ! $this->has_license() ) {
256
- return false;
257
- }
258
-
259
- return $this->using_network_license() ? $this->network_license_invalid() : $this->site_license_invalid();
260
- }
261
- public function site_license_invalid() {
262
- return ! empty( $this->site['is_invalid'] );
263
- }
264
- public function network_license_invalid(){
265
- return ! empty( $this->network['is_invalid'] );
266
- }
267
-
268
-
269
- public function get_license_error(){
270
- if ( ! $this->has_license() ) {
271
- return false;
272
- }
273
-
274
- return $this->using_network_license() ? $this->get_network_license_error() : $this->get_site_license_error();
275
- }
276
- public function get_site_license_error(){
277
- if ( $this->site_license_expired() ) {
278
- return sprintf( esc_html__( 'Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. monsterinsights_get_url( 'license-error', 'expired-license', 'https://www.monsterinsights.com/login/' ) .'" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
279
- } else if ( $this->site_license_disabled() ) {
280
- return esc_html__( 'Your license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
281
- } else if ( $this->site_license_invalid() ) {
282
- return esc_html__( 'Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
283
- }
284
- return '';
285
- }
286
-
287
- public function get_network_license_error(){
288
- if ( $this->site_license_expired() ) {
289
- return sprintf( esc_html__( 'Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s', 'google-analytics-for-wordpress' ), '<a href="'. monsterinsights_get_url( 'license-error', 'expired-license', 'https://www.monsterinsights.com/login/' ) .'" target="_blank" rel="noopener noreferrer" referrer="no-referrer">', '</a>' );
290
- } else if ( $this->site_license_disabled() ) {
291
- return esc_html__( 'Your license key for MonsterInsights has been disabled. Please use a different key.', 'google-analytics-for-wordpress' );
292
- } else if ( $this->site_license_invalid() ) {
293
- return esc_html__( 'Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key.', 'google-analytics-for-wordpress' );
294
- }
295
- return '';
296
- }
297
-
298
- public function license_can( $requires = 'lite' ) {
299
- if ( ! monsterinsights_is_pro_version() || ! $this->has_license() ) {
300
- return $requires === 'lite';
301
- }
302
- return $this->using_network_license() ? $this->network_license_can( $requires ) : $this->site_license_can( $requires );
303
- }
304
- public function site_license_can( $requires = 'lite' ) {
305
- $level = $this->get_site_license_type();
306
- $level = $level ? $level : 'lite';
307
- $can_access = false;
308
-
309
- switch ( $requires ) {
310
- case 'master':
311
- $can_access = ( $level === 'master' ) ? true : false;
312
- break;
313
-
314
- case 'pro':
315
- $can_access = ( $level === 'master' || $level === 'pro' ) ? true : false;
316
- break;
317
-
318
- case 'plus':
319
- $can_access = ( $level === 'master' || $level === 'pro' || $level === 'plus' ) ? true : false;
320
- break;
321
-
322
- case 'basic':
323
- $can_access = ( $level === 'master' || $level === 'pro' || $level === 'plus' || $level === 'basic' ) ? true : false;
324
- break;
325
-
326
- case 'lite':
327
- default:
328
- $can_access = true;
329
- break;
330
- }
331
-
332
- return $can_access;
333
- }
334
- public function network_license_can( $requires = 'lite' ) {
335
- $level = $this->get_network_license_type();
336
- $level = $level ? $level : 'lite';
337
- $can_access = false;
338
-
339
- switch ( $requires ) {
340
- case 'master':
341
- $can_access = ( $level === 'master' ) ? true : false;
342
- break;
343
-
344
- case 'pro':
345
- $can_access = ( $level === 'master' || $level === 'pro' ) ? true : false;
346
- break;
347
-
348
- case 'plus':
349
- $can_access = ( $level === 'master' || $level === 'pro' || $level === 'plus' ) ? true : false;
350
- break;
351
-
352
- case 'basic':
353
- $can_access = ( $level === 'master' || $level === 'pro' || $level === 'plus' || $level === 'basic' ) ? true : false;
354
- break;
355
-
356
- case 'lite':
357
- default:
358
- $can_access = true;
359
- break;
360
- }
361
-
362
- return $can_access;
363
- }
364
-
365
- public function get_default_license_key(){
366
- if ( defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
367
- return MONSTERINSIGHTS_LICENSE_KEY;
368
- }
369
- return '';
370
- }
371
-
372
- public function get_valid_license_key() {
373
- if ( $this->is_site_licensed() ) {
374
- return $this->get_site_license_key();
375
- } else if ( $this->is_network_licensed() ) {
376
- return $this->get_network_license_key();
377
- } else if ( $this->get_default_license_key() ) {
378
- return $this->get_default_license_key();
379
- } else {
380
- return '';
381
- }
382
- }
383
-
384
- public function is_network_admin() {
385
- return is_multisite() && is_network_admin();
386
- }
387
-
388
- public function is_valid_license_type( $type = '' ) {
389
- return ! empty( $type ) && is_string( $type ) && in_array( $type, $this->valid_license_types() );
390
- }
391
-
392
- public function valid_license_types() {
393
- return array(
394
- 'basic',
395
- 'plus',
396
- 'pro',
397
- 'master'
398
- );
399
- }
400
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/measurement-protocol.php CHANGED
@@ -1,142 +1,142 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- function monsterinsights_get_mp_api_url( ) {
7
- return 'https://www.google-analytics.com/collect';
8
- }
9
-
10
- function monsterinsights_mp_api_call( $args = array() ) {
11
- $user_agent = '';
12
- if ( ! empty( $args['user-agent'] ) ) {
13
- $user_agent = $args['user-agent'];
14
- unset( $args['user-agent'] );
15
- }
16
-
17
- $payment_id = 0;
18
- if ( ! empty( $args['payment_id'] ) ) {
19
- $payment_id = $args['payment_id'];
20
- unset( $args['payment_id'] );
21
- }
22
-
23
- $defaults = array(
24
- 't' => 'event', // Required: Hit type
25
- 'ec' => '', // Optional: Event category
26
- 'ea' => '', // Optional: Event Action
27
- 'el' => '', // Optional: Event Label
28
- 'ev' => null, // Optional: Event Value
29
- );
30
-
31
- $body = array_merge( $defaults , $args );
32
-
33
- // We want to get the user's IP address when possible
34
- $ip = '';
35
- if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) && ! filter_var( $_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP ) === false ) {
36
- $ip = $_SERVER['HTTP_CLIENT_IP'];
37
- } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) && ! filter_var( $_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP ) === false ) {
38
- $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
39
- } else {
40
- $ip = $_SERVER['REMOTE_ADDR'];
41
- }
42
-
43
- $ip = apply_filters( 'monsterinsights_mp_api_call_ip', $ip );
44
-
45
- // If possible, let's get the user's language
46
- $user_language = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) : array();
47
- $user_language = reset( $user_language );
48
- $user_language = sanitize_text_field( $user_language );
49
-
50
- $default_body = array(
51
- // Required: Version
52
- 'v' => '1',
53
-
54
- // Required: UA code
55
- 'tid' => monsterinsights_get_ua_to_output( array( 'ecommerce' => $args ) ),
56
-
57
- // Required: User visitor ID
58
- 'cid' => monsterinsights_get_client_id( $payment_id ),
59
-
60
- // Required: Type of hit (either pageview or event)
61
- 't' => 'pageview', // Required - Hit type
62
-
63
- // Optional: Was the event a non-interaction event (for bounce purposes)
64
- 'ni' => true,
65
-
66
- // Optional: Document Host Name
67
- 'dh' => str_replace( array( 'http://', 'https://' ), '', site_url() ),
68
-
69
- // Optional: Requested URI
70
- 'dp' => $_SERVER['REQUEST_URI'],
71
-
72
- // Optional: Page Title
73
- 'dt' => get_the_title(),
74
-
75
- // Optional: User language
76
- 'ul' => $user_language,
77
-
78
- // Optional: User IP address
79
- 'uip' => $ip,
80
-
81
- // Optional: User Agent
82
- 'ua' => ! empty( $user_agent ) ? $user_agent : $_SERVER['HTTP_USER_AGENT'],
83
-
84
- // Optional: Time of the event
85
- 'z' => time()
86
- );
87
-
88
- $body = wp_parse_args( $body, $default_body );
89
- $body = apply_filters( 'monsterinsights_mp_api_call', $body );
90
-
91
-
92
- // Ensure that the CID is not empty
93
- if ( empty( $body['cid'] ) ) {
94
- $body['cid'] = monsterinsights_generate_uuid();
95
- }
96
-
97
- // Unset empty values to reduce request size
98
- foreach ( $body as $key => $value ) {
99
- if ( empty( $value ) ) {
100
- unset( $body[ $key ] );
101
- }
102
- }
103
-
104
- $debug_mode = monsterinsights_is_debug_mode();
105
- $args = array(
106
- 'method' => 'POST',
107
- 'timeout' => '5',
108
- 'blocking' => ( $debug_mode ) ? true : false,
109
- 'body' => $body,
110
- );
111
-
112
- if ( ! empty( $user_agent ) ) {
113
- $args['user-agent'] = $user_agent;
114
- }
115
-
116
- $response = wp_remote_post( monsterinsights_get_mp_api_url(), $args );
117
-
118
- return $response;
119
- }
120
-
121
- function monsterinsights_mp_track_event_call( $args = array() ) {
122
- $default_args = array(
123
- // Change the default type to event
124
- 't' => 'event',
125
-
126
- // Required: Event Category
127
- 'ec' => '',
128
-
129
- // Required: Event Action
130
- 'ea' => '',
131
-
132
- // Required: Event Label
133
- 'el' => '',
134
-
135
- // Optional: Event Value
136
- 'ev' => null,
137
- );
138
- $args = wp_parse_args( $args, $default_args );
139
- //$args = apply_filters( 'monsterinsights_mp_track_event_call', $args );
140
-
141
- return monsterinsights_mp_api_call( $args );
142
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ function monsterinsights_get_mp_api_url( ) {
7
+ return 'https://www.google-analytics.com/collect';
8
+ }
9
+
10
+ function monsterinsights_mp_api_call( $args = array() ) {
11
+ $user_agent = '';
12
+ if ( ! empty( $args['user-agent'] ) ) {
13
+ $user_agent = $args['user-agent'];
14
+ unset( $args['user-agent'] );
15
+ }
16
+
17
+ $payment_id = 0;
18
+ if ( ! empty( $args['payment_id'] ) ) {
19
+ $payment_id = $args['payment_id'];
20
+ unset( $args['payment_id'] );
21
+ }
22
+
23
+ $defaults = array(
24
+ 't' => 'event', // Required: Hit type
25
+ 'ec' => '', // Optional: Event category
26
+ 'ea' => '', // Optional: Event Action
27
+ 'el' => '', // Optional: Event Label
28
+ 'ev' => null, // Optional: Event Value
29
+ );
30
+
31
+ $body = array_merge( $defaults , $args );
32
+
33
+ // We want to get the user's IP address when possible
34
+ $ip = '';
35
+ if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) && ! filter_var( $_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP ) === false ) {
36
+ $ip = $_SERVER['HTTP_CLIENT_IP'];
37
+ } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) && ! filter_var( $_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP ) === false ) {
38
+ $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
39
+ } else {
40
+ $ip = $_SERVER['REMOTE_ADDR'];
41
+ }
42
+
43
+ $ip = apply_filters( 'monsterinsights_mp_api_call_ip', $ip );
44
+
45
+ // If possible, let's get the user's language
46
+ $user_language = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) : array();
47
+ $user_language = reset( $user_language );
48
+ $user_language = sanitize_text_field( $user_language );
49
+
50
+ $default_body = array(
51
+ // Required: Version
52
+ 'v' => '1',
53
+
54
+ // Required: UA code
55
+ 'tid' => monsterinsights_get_ua_to_output( array( 'ecommerce' => $args ) ),
56
+
57
+ // Required: User visitor ID
58
+ 'cid' => monsterinsights_get_client_id( $payment_id ),
59
+
60
+ // Required: Type of hit (either pageview or event)
61
+ 't' => 'pageview', // Required - Hit type
62
+
63
+ // Optional: Was the event a non-interaction event (for bounce purposes)
64
+ 'ni' => true,
65
+
66
+ // Optional: Document Host Name
67
+ 'dh' => str_replace( array( 'http://', 'https://' ), '', site_url() ),
68
+
69
+ // Optional: Requested URI
70
+ 'dp' => $_SERVER['REQUEST_URI'],
71
+
72
+ // Optional: Page Title
73
+ 'dt' => get_the_title(),
74
+
75
+ // Optional: User language
76
+ 'ul' => $user_language,
77
+
78
+ // Optional: User IP address
79
+ 'uip' => $ip,
80
+
81
+ // Optional: User Agent
82
+ 'ua' => ! empty( $user_agent ) ? $user_agent : $_SERVER['HTTP_USER_AGENT'],
83
+
84
+ // Optional: Time of the event
85
+ 'z' => time()
86
+ );
87
+
88
+ $body = wp_parse_args( $body, $default_body );
89
+ $body = apply_filters( 'monsterinsights_mp_api_call', $body );
90
+
91
+
92
+ // Ensure that the CID is not empty
93
+ if ( empty( $body['cid'] ) ) {
94
+ $body['cid'] = monsterinsights_generate_uuid();
95
+ }
96
+
97
+ // Unset empty values to reduce request size
98
+ foreach ( $body as $key => $value ) {
99
+ if ( empty( $value ) ) {
100
+ unset( $body[ $key ] );
101
+ }
102
+ }
103
+
104
+ $debug_mode = monsterinsights_is_debug_mode();
105
+ $args = array(
106
+ 'method' => 'POST',
107
+ 'timeout' => '5',
108
+ 'blocking' => ( $debug_mode ) ? true : false,
109
+ 'body' => $body,
110
+ );
111
+
112
+ if ( ! empty( $user_agent ) ) {
113
+ $args['user-agent'] = $user_agent;
114
+ }
115
+
116
+ $response = wp_remote_post( monsterinsights_get_mp_api_url(), $args );
117
+
118
+ return $response;
119
+ }
120
+
121
+ function monsterinsights_mp_track_event_call( $args = array() ) {
122
+ $default_args = array(
123
+ // Change the default type to event
124
+ 't' => 'event',
125
+
126
+ // Required: Event Category
127
+ 'ec' => '',
128
+
129
+ // Required: Event Action
130
+ 'ea' => '',
131
+
132
+ // Required: Event Label
133
+ 'el' => '',
134
+
135
+ // Optional: Event Value
136
+ 'ev' => null,
137
+ );
138
+ $args = wp_parse_args( $args, $default_args );
139
+ //$args = apply_filters( 'monsterinsights_mp_track_event_call', $args );
140
+
141
+ return monsterinsights_mp_api_call( $args );
142
  }
includes/options.php CHANGED
@@ -1,411 +1,414 @@
1
- <?php
2
- /**
3
- * Option functions.
4
- *
5
- * @since 6.0.0
6
- *
7
- * @package MonsterInsights
8
- * @subpackage Options
9
- * @author Chris Christoff
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
- }
16
-
17
- function monsterinsights_get_options() {
18
- $settings = array();
19
- $option_name = monsterinsights_get_option_name();
20
- //$settings = get_site_option( $option_name );
21
- //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
22
- //$is_network = is_multisite();
23
-
24
- //if ( $is_network && $use_network_settings ) {
25
- // return $settings;
26
- //} else if ( $is_network ) {
27
- $settings = get_option( $option_name );
28
- //} else {
29
- // return $settings;
30
- //}
31
- if ( empty( $settings ) || ! is_array( $settings ) ) {
32
- $settings = array();
33
- }
34
- return $settings;
35
- }
36
-
37
- /**
38
- * Helper method for getting a setting's value. Falls back to the default
39
- * setting value if none exists in the options table.
40
- *
41
- * @since 6.0.0
42
- * @access public
43
- *
44
- * @param string $key The setting key to retrieve.
45
- * @param mixed $default The default value of the setting key to retrieve.
46
- * @return string The value of the setting.
47
- */
48
- function monsterinsights_get_option( $key = '', $default = false ) {
49
- global $monsterinsights_settings;
50
- $value = ! empty( $monsterinsights_settings[ $key ] ) ? $monsterinsights_settings[ $key ] : $default;
51
- $value = apply_filters( 'monsterinsights_get_option', $value, $key, $default );
52
- return apply_filters( 'monsterinsights_get_option_' . $key, $value, $key, $default );
53
- }
54
-
55
- /**
56
- * Helper method for getting the UA string.
57
- *
58
- * @since 6.0.0
59
- * @access public
60
- *
61
- * @return string The UA to use.
62
- */
63
- function monsterinsights_get_ua() {
64
- // Try getting it from the auth UA
65
- $ua = MonsterInsights()->auth->get_ua();
66
-
67
- // If that didn't work, try the manual UA at the site level
68
- if ( empty( $ua ) ) {
69
- $ua = MonsterInsights()->auth->get_manual_ua();
70
- // If that didn't work try getting it from the network
71
- if ( empty( $ua ) ) {
72
- $ua = monsterinsights_get_network_ua();
73
- // If that didn't work, try getting it from the overall constant. If it's not there, leave it blank
74
- if ( empty( $ua ) ) {
75
- $ua = defined( 'MONSTERINSIGHTS_GA_UA' ) && MONSTERINSIGHTS_GA_UA ? monsterinsights_is_valid_ua( MONSTERINSIGHTS_GA_UA ) : '';
76
- }
77
- }
78
- }
79
-
80
- // Feed through the filter
81
- $pre_filter = $ua;
82
- $ua = apply_filters( 'monsterinsights_get_ua', $ua );
83
-
84
- // Only run through monsterinsights_is_valid_ua if it's different than pre-filter
85
- return $pre_filter === $ua ? $ua : monsterinsights_is_valid_ua( $ua );
86
- }
87
-
88
- /**
89
- * Helper method for getting the network UA string.
90
- *
91
- * @since 6.0.0
92
- * @access public
93
- *
94
- * @return string The UA to use.
95
- */
96
- function monsterinsights_get_network_ua() {
97
- if ( ! is_multisite() ) {
98
- return '';
99
- }
100
-
101
- // First try network auth UA
102
- $ua = MonsterInsights()->auth->get_network_ua();
103
- if ( ! empty( $ua ) ) {
104
- return $ua;
105
- }
106
-
107
- // Then try manual network UA
108
- $ua = MonsterInsights()->auth->get_network_manual_ua();
109
- if ( ! empty( $ua ) ) {
110
- return $ua;
111
- }
112
-
113
- // See if the constant is defined
114
- if ( defined( 'MONSTERINSIGHTS_MS_GA_UA' ) && monsterinsights_is_valid_ua( MONSTERINSIGHTS_MS_GA_UA ) ) {
115
- return MONSTERINSIGHTS_MS_GA_UA;
116
- }
117
-
118
- return '';
119
- }
120
-
121
- /**
122
- * Helper method for getting the UA string that's output on the frontend.
123
- *
124
- * @since 6.0.0
125
- * @access public
126
- *
127
- * @param array $args Allow calling functions to give args to use in future applications.
128
- * @return string The UA to use on frontend.
129
- */
130
- function monsterinsights_get_ua_to_output( $args = array() ) {
131
- $ua = monsterinsights_get_ua();
132
- $ua = apply_filters( 'monsterinsights_get_ua_to_output', $ua, $args );
133
- return monsterinsights_is_valid_ua( $ua );
134
- }
135
-
136
- /**
137
- * Helper method for updating a setting's value.
138
- *
139
- * @since 6.0.0
140
- * @access public
141
- *
142
- * @param string $key The setting key.
143
- * @param string $value The value to set for the key.
144
- * @return boolean True if updated, false if not.
145
- */
146
- function monsterinsights_update_option( $key = '', $value = false ) {
147
-
148
- // If no key, exit
149
- if ( empty( $key ) ){
150
- return false;
151
- }
152
-
153
- if ( empty( $value ) ) {
154
- $remove_option = monsterinsights_delete_option( $key );
155
- return $remove_option;
156
- }
157
-
158
- $option_name = monsterinsights_get_option_name();
159
-
160
- // First let's grab the current settings
161
-
162
- // if on network panel or if on single site using network settings
163
- //$settings = get_site_option( $option_name );
164
- //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
165
- //$is_network = is_multisite();
166
- //$update_network_option = true;
167
- //if ( ! is_network_admin() && ! ( $is_network && $use_network_settings ) ) {
168
- $settings = get_option( $option_name );
169
- // $update_network_option = false;
170
- //}
171
-
172
- if ( ! is_array( $settings ) ) {
173
- $settings = array();
174
- }
175
-
176
- // Let's let devs alter that value coming in
177
- $value = apply_filters( 'monsterinsights_update_option', $value, $key );
178
-
179
- // Next let's try to update the value
180
- $settings[ $key ] = $value;
181
- $did_update = false;
182
- //if ( $update_network_option ) {
183
- // $did_update = update_site_option( $option_name, $settings );
184
- //} else {
185
- $did_update = update_option( $option_name, $settings );
186
- //}
187
-
188
- // If it updated, let's update the global variable
189
- if ( $did_update ){
190
- global $monsterinsights_settings;
191
- $monsterinsights_settings[ $key ] = $value;
192
- }
193
-
194
- return $did_update;
195
- }
196
-
197
- /**
198
- * Helper method for deleting a setting's value.
199
- *
200
- * @since 6.0.0
201
- * @access public
202
- *
203
- * @param string $key The setting key.
204
- * @return boolean True if removed, false if not.
205
- */
206
- function monsterinsights_delete_option( $key = '' ) {
207
- // If no key, exit
208
- if ( empty( $key ) ){
209
- return false;
210
- }
211
-
212
- $option_name = monsterinsights_get_option_name();
213
-
214
- // First let's grab the current settings
215
-
216
- // if on network panel or if on single site using network settings
217
- //$settings = get_site_option( $option_name );
218
- //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
219
- //$is_network = is_multisite();
220
- //$update_network_option = true;
221
- //if ( ! is_network_admin() && ! ( $is_network && $use_network_settings ) ) {
222
- $settings = get_option( $option_name );
223
- // $update_network_option = false;
224
- //}
225
-
226
- // Next let's try to remove the key
227
- if( isset( $settings[ $key ] ) ) {
228
- unset( $settings[ $key ] );
229
- }
230
-
231
- $did_update = false;
232
- //if ( $update_network_option ) {
233
- // $did_update = update_site_option( 'monsterinsights_settings', $settings );
234
- //} else {
235
- $did_update = update_option( $option_name, $settings );
236
- //}
237
-
238
- // If it updated, let's update the global variable
239
- if ( $did_update ){
240
- global $monsterinsights_settings;
241
- $monsterinsights_settings = $settings;
242
- }
243
-
244
- return $did_update;
245
- }
246
-
247
- /**
248
- * Helper method for deleting multiple settings value.
249
- *
250
- * @since 6.0.0
251
- * @access public
252
- *
253
- * @param string $key The setting key.
254
- * @return boolean True if removed, false if not.
255
- */
256
- function monsterinsights_delete_options( $keys = array() ) {
257
- // If no keys, exit
258
- if ( empty( $keys ) || ! is_array( $keys ) ){
259
- return false;
260
- }
261
-
262
- $option_name = monsterinsights_get_option_name();
263
-
264
- // First let's grab the current settings
265
-
266
- // if on network panel or if on single site using network settings
267
- //$settings = get_site_option( $option_name );
268
- //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
269
- //$is_network = is_multisite();
270
- //$update_network_option = true;
271
- //if ( ! is_network_admin() && ! ( $is_network && $use_network_settings ) ) {
272
- $settings = get_option( $option_name );
273
- // $update_network_option = false;
274
- //}
275
-
276
- // Next let's try to remove the keys
277
- foreach ( $keys as $key ) {
278
- if( isset( $settings[ $key ] ) ) {
279
- unset( $settings[ $key ] );
280
- }
281
- }
282
-
283
- $did_update = false;
284
- //if ( $update_network_option ) {
285
- // $did_update = update_site_option( 'monsterinsights_settings', $settings );
286
- //} else {
287
- $did_update = update_option( $option_name, $settings );
288
- //}
289
-
290
- // If it updated, let's update the global variable
291
- if ( $did_update ){
292
- global $monsterinsights_settings;
293
- $monsterinsights_settings = $settings;
294
- }
295
-
296
- return $did_update;
297
- }
298
-
299
- /**
300
- * Is valid ua code.
301
- *
302
- * @access public
303
- * @since 6.0.0
304
- *
305
- * @param string $ua_code UA code to check validity for.
306
- *
307
- * @return string|false Return cleaned ua string if valid, else returns false.
308
- */
309
- function monsterinsights_is_valid_ua( $ua_code = '' ) {
310
- $ua_code = (string) $ua_code; // Rare case, but let's make sure it never happens.
311
- $ua_code = trim( $ua_code );
312
-
313
- if ( empty( $ua_code ) ) {
314
- return '';
315
- }
316
-
317
- // Replace all type of dashes (n-dash, m-dash, minus) with normal dashes.
318
- $ua_code = str_replace( array( '–', '—', '−' ), '-', $ua_code );
319
-
320
- if ( preg_match( "/^(UA|YT|MO)-\d{4,}-\d+$/", strval( $ua_code ) ) ) {
321
- return $ua_code;
322
- } else {
323
- return '';
324
- }
325
- }
326
-
327
- /**
328
- * Helper method for getting the license information.
329
- *
330
- * @since 6.0.0
331
- * @access public
332
- *
333
- * @param string $key The setting key to retrieve.
334
- * @param mixed $default_value The default value of the setting key to retrieve.
335
- * @return string The value of the setting.
336
- */
337
- function monsterinsights_get_license() {
338
- $license = MonsterInsights()->license->get_site_license();
339
- $license = $license ? $license : MonsterInsights()->license->get_network_license();
340
- $default = MonsterInsights()->license->get_default_license_key();
341
- if ( empty( $license ) && ! empty( $default ) ) {
342
- $license = array();
343
- $license['key'] = MonsterInsights()->license->get_default_license_key();
344
- }
345
- return $license;
346
- }
347
-
348
- /**
349
- * Helper method for getting the license key.
350
- *
351
- * @since 6.0.0
352
- * @access public
353
- *
354
- * @param string $key The setting key to retrieve.
355
- * @param mixed $default_value The default value of the setting key to retrieve.
356
- * @return string The value of the setting.
357
- */
358
- function monsterinsights_get_license_key() {
359
- return MonsterInsights()->license->get_license_key();
360
- }
361
-
362
- function monsterinsights_get_option_name() {
363
- //if ( monsterinsights_is_pro_version() ) {
364
- return 'monsterinsights_settings';
365
- //} else {
366
- // return 'monsterinsights_settings';
367
- //}
368
- }
369
-
370
- function monsterinsights_export_settings() {
371
- $settings = monsterinsights_get_options();
372
- $exclude = array(
373
- 'analytics_profile',
374
- 'analytics_profile_code',
375
- 'analytics_profile_name',
376
- 'oauth_version',
377
- 'cron_last_run',
378
- 'monsterinsights_oauth_status',
379
- );
380
-
381
- foreach ( $exclude as $e ) {
382
- if ( ! empty( $settings[ $e ] ) ) {
383
- unset( $settings[ $e ] );
384
- }
385
- }
386
- return wp_json_encode( $settings );
387
- }
388
-
389
- /**
390
- * Always return 'analytics' when grabbing the tracking mode.
391
- *
392
- * @param string $value The value to override.
393
- *
394
- * @return string
395
- */
396
- function monsterinsights_force_tracking_mode( $value ) {
397
- return 'analytics';
398
- }
399
- add_filter( 'monsterinsights_get_option_tracking_mode', 'monsterinsights_force_tracking_mode' );
400
-
401
- /**
402
- * Always return 'js' when grabbing the events mode.
403
- *
404
- * @param string $value The value to override.
405
- *
406
- * @return string
407
- */
408
- function monsterinsights_force_events_mode( $value ) {
409
- return 'js';
410
- }
411
- add_filter( 'monsterinsights_get_option_events_mode', 'monsterinsights_force_events_mode' );
 
 
 
1
+ <?php
2
+ /**
3
+ * Option functions.
4
+ *
5
+ * @since 6.0.0
6
+ *
7
+ * @package MonsterInsights
8
+ * @subpackage Options
9
+ * @author Chris Christoff
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
+
17
+ function monsterinsights_get_options() {
18
+ $settings = array();
19
+ $option_name = monsterinsights_get_option_name();
20
+ //$settings = get_site_option( $option_name );
21
+ //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
22
+ //$is_network = is_multisite();
23
+
24
+ //if ( $is_network && $use_network_settings ) {
25
+ // return $settings;
26
+ //} else if ( $is_network ) {
27
+ $settings = get_option( $option_name );
28
+ //} else {
29
+ // return $settings;
30
+ //}
31
+ if ( empty( $settings ) || ! is_array( $settings ) ) {
32
+ $settings = array();
33
+ }
34
+ return $settings;
35
+ }
36
+
37
+ /**
38
+ * Helper method for getting a setting's value. Falls back to the default
39
+ * setting value if none exists in the options table.
40
+ *
41
+ * @since 6.0.0
42
+ * @access public
43
+ *
44
+ * @param string $key The setting key to retrieve.
45
+ * @param mixed $default The default value of the setting key to retrieve.
46
+ * @return string The value of the setting.
47
+ */
48
+ function monsterinsights_get_option( $key = '', $default = false ) {
49
+ global $monsterinsights_settings;
50
+ $value = ! empty( $monsterinsights_settings[ $key ] ) ? $monsterinsights_settings[ $key ] : $default;
51
+ $value = apply_filters( 'monsterinsights_get_option', $value, $key, $default );
52
+ return apply_filters( 'monsterinsights_get_option_' . $key, $value, $key, $default );
53
+ }
54
+
55
+ /**
56
+ * Helper method for getting the UA string.
57
+ *
58
+ * @since 6.0.0
59
+ * @access public
60
+ *
61
+ * @return string The UA to use.
62
+ */
63
+ function monsterinsights_get_ua() {
64
+ // Try getting it from the auth UA
65
+ $ua = MonsterInsights()->auth->get_ua();
66
+
67
+ // If that didn't work, try the manual UA at the site level
68
+ if ( empty( $ua ) ) {
69
+ $ua = MonsterInsights()->auth->get_manual_ua();
70
+ // If that didn't work try getting it from the network
71
+ if ( empty( $ua ) ) {
72
+ $ua = monsterinsights_get_network_ua();
73
+ // If that didn't work, try getting it from the overall constant. If it's not there, leave it blank
74
+ if ( empty( $ua ) ) {
75
+ $ua = defined( 'MONSTERINSIGHTS_GA_UA' ) && MONSTERINSIGHTS_GA_UA ? monsterinsights_is_valid_ua( MONSTERINSIGHTS_GA_UA ) : '';
76
+ }
77
+ }
78
+ }
79
+
80
+ // Feed through the filter
81
+ $pre_filter = $ua;
82
+ $ua = apply_filters( 'monsterinsights_get_ua', $ua );
83
+
84
+ // Only run through monsterinsights_is_valid_ua if it's different than pre-filter
85
+ return $pre_filter === $ua ? $ua : monsterinsights_is_valid_ua( $ua );
86
+ }
87
+
88
+ /**
89
+ * Helper method for getting the network UA string.
90
+ *
91
+ * @since 6.0.0
92
+ * @access public
93
+ *
94
+ * @return string The UA to use.
95
+ */
96
+ function monsterinsights_get_network_ua() {
97
+ if ( ! is_multisite() ) {
98
+ return '';
99
+ }
100
+
101
+ // First try network auth UA
102
+ $ua = MonsterInsights()->auth->get_network_ua();
103
+ if ( ! empty( $ua ) ) {
104
+ return $ua;
105
+ }
106
+
107
+ // Then try manual network UA
108
+ $ua = MonsterInsights()->auth->get_network_manual_ua();
109
+ if ( ! empty( $ua ) ) {
110
+ return $ua;
111
+ }
112
+
113
+ // See if the constant is defined
114
+ if ( defined( 'MONSTERINSIGHTS_MS_GA_UA' ) && monsterinsights_is_valid_ua( MONSTERINSIGHTS_MS_GA_UA ) ) {
115
+ return MONSTERINSIGHTS_MS_GA_UA;
116
+ }
117
+
118
+ return '';
119
+ }
120
+
121
+ /**
122
+ * Helper method for getting the UA string that's output on the frontend.
123
+ *
124
+ * @since 6.0.0
125
+ * @access public
126
+ *
127
+ * @param array $args Allow calling functions to give args to use in future applications.
128
+ * @return string The UA to use on frontend.
129
+ */
130
+ function monsterinsights_get_ua_to_output( $args = array() ) {
131
+ $ua = monsterinsights_get_ua();
132
+ $ua = apply_filters( 'monsterinsights_get_ua_to_output', $ua, $args );
133
+ return monsterinsights_is_valid_ua( $ua );
134
+ }
135
+
136
+ /**
137
+ * Helper method for updating a setting's value.
138
+ *
139
+ * @since 6.0.0
140
+ * @access public
141
+ *
142
+ * @param string $key The setting key.
143
+ * @param string $value The value to set for the key.
144
+ * @return boolean True if updated, false if not.
145
+ */
146
+ function monsterinsights_update_option( $key = '', $value = false ) {
147
+
148
+ // If no key, exit
149
+ if ( empty( $key ) ){
150
+ return false;
151
+ }
152
+
153
+ if ( empty( $value ) ) {
154
+ $remove_option = monsterinsights_delete_option( $key );
155
+ return $remove_option;
156
+ }
157
+
158
+ $option_name = monsterinsights_get_option_name();
159
+
160
+ // First let's grab the current settings
161
+
162
+ // if on network panel or if on single site using network settings
163
+ //$settings = get_site_option( $option_name );
164
+ //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
165
+ //$is_network = is_multisite();
166
+ //$update_network_option = true;
167
+ //if ( ! is_network_admin() && ! ( $is_network && $use_network_settings ) ) {
168
+ $settings = get_option( $option_name );
169
+ // $update_network_option = false;
170
+ //}
171
+
172
+ if ( ! is_array( $settings ) ) {
173
+ $settings = array();
174
+ }
175
+
176
+ // Let's let devs alter that value coming in
177
+ $value = apply_filters( 'monsterinsights_update_option', $value, $key );
178
+
179
+ // Next let's try to update the value
180
+ $settings[ $key ] = $value;
181
+ $did_update = false;
182
+ //if ( $update_network_option ) {
183
+ // $did_update = update_site_option( $option_name, $settings );
184
+ //} else {
185
+ $did_update = update_option( $option_name, $settings );
186
+ //}
187
+
188
+ // If it updated, let's update the global variable
189
+ if ( $did_update ){
190
+ global $monsterinsights_settings;
191
+ $monsterinsights_settings[ $key ] = $value;
192
+ }
193
+
194
+ return $did_update;
195
+ }
196
+
197
+ /**
198
+ * Helper method for deleting a setting's value.
199
+ *
200
+ * @since 6.0.0
201
+ * @access public
202
+ *
203
+ * @param string $key The setting key.
204
+ * @return boolean True if removed, false if not.
205
+ */
206
+ function monsterinsights_delete_option( $key = '' ) {
207
+ // If no key, exit
208
+ if ( empty( $key ) ){
209
+ return false;
210
+ }
211
+
212
+ $option_name = monsterinsights_get_option_name();
213
+
214
+ // First let's grab the current settings
215
+
216
+ // if on network panel or if on single site using network settings
217
+ //$settings = get_site_option( $option_name );
218
+ //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
219
+ //$is_network = is_multisite();
220
+ //$update_network_option = true;
221
+ //if ( ! is_network_admin() && ! ( $is_network && $use_network_settings ) ) {
222
+ $settings = get_option( $option_name );
223
+ // $update_network_option = false;
224
+ //}
225
+
226
+ // Next let's try to remove the key
227
+ if( isset( $settings[ $key ] ) ) {
228
+ unset( $settings[ $key ] );
229
+ }
230
+
231
+ $did_update = false;
232
+ //if ( $update_network_option ) {
233
+ // $did_update = update_site_option( 'monsterinsights_settings', $settings );
234
+ //} else {
235
+ $did_update = update_option( $option_name, $settings );
236
+ //}
237
+
238
+ // If it updated, let's update the global variable
239
+ if ( $did_update ){
240
+ global $monsterinsights_settings;
241
+ $monsterinsights_settings = $settings;
242
+ }
243
+
244
+ return $did_update;
245
+ }
246
+
247
+ /**
248
+ * Helper method for deleting multiple settings value.
249
+ *
250
+ * @since 6.0.0
251
+ * @access public
252
+ *
253
+ * @param string $key The setting key.
254
+ * @return boolean True if removed, false if not.
255
+ */
256
+ function monsterinsights_delete_options( $keys = array() ) {
257
+ // If no keys, exit
258
+ if ( empty( $keys ) || ! is_array( $keys ) ){
259
+ return false;
260
+ }
261
+
262
+ $option_name = monsterinsights_get_option_name();
263
+
264
+ // First let's grab the current settings
265
+
266
+ // if on network panel or if on single site using network settings
267
+ //$settings = get_site_option( $option_name );
268
+ //$use_network_settings = ! empty( $use_network_settings['use_network_settings'] ) ? true : false;
269
+ //$is_network = is_multisite();
270
+ //$update_network_option = true;
271
+ //if ( ! is_network_admin() && ! ( $is_network && $use_network_settings ) ) {
272
+ $settings = get_option( $option_name );
273
+ // $update_network_option = false;
274
+ //}
275
+
276
+ // Next let's try to remove the keys
277
+ foreach ( $keys as $key ) {
278
+ if( isset( $settings[ $key ] ) ) {
279
+ unset( $settings[ $key ] );
280
+ }
281
+ }
282
+
283
+ $did_update = false;
284
+ //if ( $update_network_option ) {
285
+ // $did_update = update_site_option( 'monsterinsights_settings', $settings );
286
+ //} else {
287
+ $did_update = update_option( $option_name, $settings );
288
+ //}
289
+
290
+ // If it updated, let's update the global variable
291
+ if ( $did_update ){
292
+ global $monsterinsights_settings;
293
+ $monsterinsights_settings = $settings;
294
+ }
295
+
296
+ return $did_update;
297
+ }
298
+
299
+ /**
300
+ * Is valid ua code.
301
+ *
302
+ * @access public
303
+ * @since 6.0.0
304
+ *
305
+ * @param string $ua_code UA code to check validity for.
306
+ *
307
+ * @return string|false Return cleaned ua string if valid, else returns false.
308
+ */
309
+ function monsterinsights_is_valid_ua( $ua_code = '' ) {
310
+ $ua_code = (string) $ua_code; // Rare case, but let's make sure it never happens.
311
+ $ua_code = trim( $ua_code );
312
+
313
+ if ( empty( $ua_code ) ) {
314
+ return '';
315
+ }
316
+
317
+ // Replace all type of dashes (n-dash, m-dash, minus) with normal dashes.
318
+ $ua_code = str_replace( array( '–', '—', '−' ), '-', $ua_code );
319
+
320
+ if ( preg_match( "/^(UA|YT|MO)-\d{4,}-\d+$/", strval( $ua_code ) ) ) {
321
+ return $ua_code;
322
+ } else {
323
+ return '';
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Helper method for getting the license information.
329
+ *
330
+ * @since 6.0.0
331
+ * @access public
332
+ *
333
+ * @param string $key The setting key to retrieve.
334
+ * @param mixed $default_value The default value of the setting key to retrieve.
335
+ * @return string The value of the setting.
336
+ */
337
+ function monsterinsights_get_license() {
338
+ $license = MonsterInsights()->license->get_site_license();
339
+ $license = $license ? $license : MonsterInsights()->license->get_network_license();
340
+ $default = MonsterInsights()->license->get_default_license_key();
341
+ if ( empty( $license ) && ! empty( $default ) ) {
342
+ $license = array();
343
+ $license['key'] = MonsterInsights()->license->get_default_license_key();
344
+ }
345
+ return $license;
346
+ }
347
+
348
+ /**
349
+ * Helper method for getting the license key.
350
+ *
351
+ * @since 6.0.0
352
+ * @access public
353
+ *
354
+ * @param string $key The setting key to retrieve.
355
+ * @param mixed $default_value The default value of the setting key to retrieve.
356
+ * @return string The value of the setting.
357
+ */
358
+ function monsterinsights_get_license_key() {
359
+ if ( monsterinsights_is_pro_version() ) {
360
+ return MonsterInsights()->license->get_license_key();
361
+ }
362
+ return '';
363
+ }
364
+
365
+ function monsterinsights_get_option_name() {
366
+ //if ( monsterinsights_is_pro_version() ) {
367
+ return 'monsterinsights_settings';
368
+ //} else {
369
+ // return 'monsterinsights_settings';
370
+ //}
371
+ }
372
+
373
+ function monsterinsights_export_settings() {
374
+ $settings = monsterinsights_get_options();
375
+ $exclude = array(
376
+ 'analytics_profile',
377
+ 'analytics_profile_code',
378
+ 'analytics_profile_name',
379
+ 'oauth_version',
380
+ 'cron_last_run',
381
+ 'monsterinsights_oauth_status',
382
+ );
383
+
384
+ foreach ( $exclude as $e ) {
385
+ if ( ! empty( $settings[ $e ] ) ) {
386
+ unset( $settings[ $e ] );
387
+ }
388
+ }
389
+ return wp_json_encode( $settings );
390
+ }
391
+
392
+ /**
393
+ * Always return 'analytics' when grabbing the tracking mode.
394
+ *
395
+ * @param string $value The value to override.
396
+ *
397
+ * @return string
398
+ */
399
+ function monsterinsights_force_tracking_mode( $value ) {
400
+ return 'analytics';
401
+ }
402
+ add_filter( 'monsterinsights_get_option_tracking_mode', 'monsterinsights_force_tracking_mode' );
403
+
404
+ /**
405
+ * Always return 'js' when grabbing the events mode.
406
+ *
407
+ * @param string $value The value to override.
408
+ *
409
+ * @return string
410
+ */
411
+ function monsterinsights_force_events_mode( $value ) {
412
+ return 'js';
413
+ }
414
+ add_filter( 'monsterinsights_get_option_events_mode', 'monsterinsights_force_events_mode' );
index.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
- //Nothing to see here
3
-
4
  header( 'HTTP/1.0 403 Forbidden' );
1
+ <?php
2
+ //Nothing to see here
3
+
4
  header( 'HTTP/1.0 403 Forbidden' );
languages/google-analytics-for-wordpress.pot CHANGED
@@ -2,14 +2,14 @@
2
  # This file is distributed under the same license as the MonsterInsights Pro plugin.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: MonsterInsights Pro 7.7.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/monsterinsights\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "POT-Creation-Date: 2019-06-18T15:41:49+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.2.0\n"
15
  "X-Domain: google-analytics-for-wordpress\n"
@@ -27,17 +27,18 @@ msgid "The best Google Analytics plugin for WordPress. See how visitors find and
27
  msgstr ""
28
 
29
  #. Author of the plugin
 
 
 
 
 
 
 
 
 
30
  #: includes/admin/admin.php:38
31
  #: includes/admin/admin.php:41
32
  #: includes/admin/admin.php:51
33
- #: lite/includes/admin/dashboard-widget.php:90
34
- #: lite/includes/admin/wp-site-health.php:167
35
- #: lite/includes/admin/wp-site-health.php:219
36
- #: lite/includes/admin/wp-site-health.php:246
37
- #: lite/includes/admin/wp-site-health.php:284
38
- #: lite/includes/admin/wp-site-health.php:311
39
- #: lite/includes/admin/wp-site-health.php:338
40
- #: lite/includes/admin/wp-site-health.php:363
41
  msgid "MonsterInsights"
42
  msgstr ""
43
 
@@ -45,304 +46,628 @@ msgstr ""
45
  msgid "https://www.monsterinsights.com/?utm_source=proplugin&utm_medium=pluginheader&utm_campaign=authoruri&utm_content=7%2E0%2E0"
46
  msgstr ""
47
 
48
- #: googleanalytics.php:272
49
- #: googleanalytics.php:286
50
- msgid "Cheatin&#8217; huh?"
51
  msgstr ""
52
 
53
- #: googleanalytics.php:422
54
- msgid "Sorry, but your version of WordPress does not meet MonsterInsights's required version of %1$s3.8%2$s to run properly. The plugin not been activated. %3$sClick here to return to the Dashboard%4$s."
55
  msgstr ""
56
 
57
- #: googleanalytics.php:443
58
- msgid "Please %1$suninstall%2$s the MonsterInsights Lite Plugin. Your Pro version of MonsterInsights may not work as expected until the Lite version is uninstalled."
59
  msgstr ""
60
 
61
- #: includes/admin/admin.php:38
62
- #: includes/admin/admin.php:44
63
- #: includes/admin/admin.php:54
64
- #: includes/admin/admin.php:93
65
- #: languages/vue.php:167
66
- msgid "Insights"
67
  msgstr ""
68
 
69
- #: includes/admin/admin.php:41
70
- #: includes/admin/admin.php:51
71
- #: includes/admin/admin.php:179
72
- msgid "Settings"
73
  msgstr ""
74
 
75
- #: includes/admin/admin.php:44
76
- msgid "General:"
77
  msgstr ""
78
 
79
- #: includes/admin/admin.php:48
80
- #: includes/admin/admin.php:54
81
- #: includes/admin/admin.php:97
82
- msgid "General Reports:"
83
  msgstr ""
84
 
85
- #: includes/admin/admin.php:48
86
- #: includes/admin/admin.php:97
87
- #: languages/vue.php:608
88
- msgid "Reports"
89
  msgstr ""
90
 
91
- #: includes/admin/admin.php:60
92
- msgid "Tools:"
 
93
  msgstr ""
94
 
95
- #: includes/admin/admin.php:60
96
- msgid "Tools"
97
  msgstr ""
98
 
99
- #: includes/admin/admin.php:65
100
- #: includes/admin/admin.php:100
101
- msgid "Addons:"
102
  msgstr ""
103
 
104
- #: includes/admin/admin.php:65
105
- #: includes/admin/admin.php:100
106
- msgid "Addons"
107
  msgstr ""
108
 
109
- #: includes/admin/admin.php:69
110
- msgid "About Us:"
111
  msgstr ""
112
 
113
- #: includes/admin/admin.php:69
114
- #: languages/vue.php:234
115
- msgid "About Us"
116
  msgstr ""
117
 
118
- #: includes/admin/admin.php:93
119
- #: includes/admin/admin.php:95
120
- msgid "Network Settings:"
121
  msgstr ""
122
 
123
- #: includes/admin/admin.php:95
124
- msgid "Network Settings"
125
  msgstr ""
126
 
127
- #: includes/admin/admin.php:161
128
- msgid "MonsterInsights Knowledge Base"
129
  msgstr ""
130
 
131
- #: includes/admin/admin.php:161
132
- msgid "Documentation"
133
  msgstr ""
134
 
135
- #: includes/admin/admin.php:166
136
- #: includes/admin/reports/abstract-report.php:358
137
- msgid "Get MonsterInsights Pro"
138
  msgstr ""
139
 
140
- #: includes/admin/admin.php:172
141
- #: includes/admin/admin.php:175
142
- #: languages/vue.php:945
143
- msgid "Support"
144
  msgstr ""
145
 
146
- #: includes/admin/admin.php:238
147
- msgid "Please rate %sMonsterInsights%s %s on %sWordPress.org%s to help us spread the word. Thank you from the MonsterInsights team!"
148
  msgstr ""
149
 
150
- #: includes/admin/admin.php:272
151
- msgid "Please configure your %1$sGoogle Analytics settings%2$s!"
152
  msgstr ""
153
 
154
- #: includes/admin/admin.php:281
155
- msgid "Warning: No valid license key has been entered for MonsterInsights. You are currently not getting updates, and are not able to view reports. %1$sPlease click here to enter your license key and begin receiving updates and reports.%2$s"
156
  msgstr ""
157
 
158
- #. Translators: The link to the MonsterInsights website.
159
- #: includes/admin/admin.php:291
160
- #: includes/admin/licensing/license-actions.php:298
161
- #: includes/license.php:278
162
- #: includes/license.php:289
163
- msgid "Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s"
164
  msgstr ""
165
 
166
- #: includes/admin/admin.php:293
167
- #: includes/admin/licensing/license-actions.php:307
168
- #: includes/license.php:280
169
- #: includes/license.php:291
170
- #: languages/vue.php:1242
171
- msgid "Your license key for MonsterInsights has been disabled. Please use a different key."
172
  msgstr ""
173
 
174
- #: includes/admin/admin.php:295
175
- #: includes/admin/licensing/license-actions.php:288
176
- #: includes/license.php:282
177
- #: includes/license.php:293
178
- #: languages/vue.php:1245
179
- msgid "Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key."
180
  msgstr ""
181
 
182
- #: includes/admin/admin.php:299
183
- msgid "Your network license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s"
 
 
184
  msgstr ""
185
 
186
- #: includes/admin/admin.php:301
187
- msgid "Your network license key for MonsterInsights has been disabled. Please use a different key."
188
  msgstr ""
189
 
190
- #: includes/admin/admin.php:303
191
- msgid "Your network license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key."
192
  msgstr ""
193
 
194
- #: includes/admin/admin.php:319
195
- msgid "Your site is running an outdated, insecure version of PHP (%1$s), which could be putting your site at risk for being hacked.%4$sWordPress will stop supporting your PHP version in April, 2019.%4$sUpdating PHP only takes a few minutes and will make your website significantly faster and more secure.%4$s%2$sLearn more about updating PHP%3$s"
196
  msgstr ""
197
 
198
- #: includes/admin/admin.php:326
199
- msgid "Your site is running an outdated version of WordPress (%1$s).%4$sMonsterInsights will stop supporting WordPress versions lower than 4.6 in April, 2019.%4$sUpdating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install.%4$s%2$sLearn more about updating WordPress%3$s"
200
  msgstr ""
201
 
202
- #: includes/admin/admin.php:383
203
- msgid "Important: You are currently using manual UA code output. We highly recommend %1$sauthenticating with MonsterInsights%2$s so that you can access our new reporting area and take advantage of new MonsterInsights features."
204
  msgstr ""
205
 
206
- #: includes/admin/admin.php:425
207
- #: includes/admin/admin.php:456
208
- msgid "%1$sGet MonsterInsights Pro%2$s"
209
  msgstr ""
210
 
211
- #: includes/admin/admin.php:469
212
- msgid "Warning: MonsterInsights found cross-domain settings in the custom code field and converted them to the new settings structure. %1$sPlease click here to review and remove the code no longer needed.%2$s"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  msgstr ""
214
 
215
  #: includes/admin/api-auth.php:85
216
  msgid "You don't have permission to authenticate MonsterInsights."
217
  msgstr ""
218
 
219
- #: includes/admin/api-auth.php:95
220
  msgid "Cannot authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings."
221
  msgstr ""
222
 
223
- #: includes/admin/api-auth.php:100
224
  msgid "Cannot authenticate. Please re-authenticate."
225
  msgstr ""
226
 
227
- #: includes/admin/api-auth.php:102
228
  msgid "Cannot network authenticate. Please re-authenticate on the network settings panel."
229
  msgstr ""
230
 
231
- #: includes/admin/api-auth.php:238
232
  msgid "You don't have permission to re-authenticate MonsterInsights."
233
  msgstr ""
234
 
235
- #: includes/admin/api-auth.php:248
236
- msgid "Cannot re-authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  msgstr ""
238
 
239
- #: includes/admin/api-auth.php:253
240
- msgid "Cannot re-authenticate. Please authenticate."
241
  msgstr ""
242
 
243
- #: includes/admin/api-auth.php:255
244
- msgid "Cannot re-authenticate the network. Please authenticate on the network settings panel."
 
245
  msgstr ""
246
 
247
- #: includes/admin/api-auth.php:357
248
- msgid "You don't have permission to verify MonsterInsights."
 
249
  msgstr ""
250
 
251
- #: includes/admin/api-auth.php:366
252
- #: includes/admin/api-auth.php:368
253
- msgid "Cannot verify. Please authenticate."
254
  msgstr ""
255
 
256
- #: includes/admin/api-auth.php:373
257
- msgid "Cannot verify. Please enter a valid, active license key for MonsterInsights Pro into the settings."
 
258
  msgstr ""
259
 
260
- #: includes/admin/api-auth.php:378
261
- msgid "Successfully verified."
 
262
  msgstr ""
263
 
264
- #: includes/admin/api-auth.php:380
265
- msgid "Could not verify."
266
  msgstr ""
267
 
268
- #: includes/admin/api-auth.php:388
269
- msgid "Verify auth key not passed"
270
  msgstr ""
271
 
272
- #: includes/admin/api-auth.php:410
273
- msgid "You don't have permission to deauthenticate MonsterInsights."
274
  msgstr ""
275
 
276
- #: includes/admin/api-auth.php:419
277
- #: includes/admin/api-auth.php:421
278
- msgid "Cannot deauthenticate. You are not currently authed."
279
  msgstr ""
280
 
281
- #: includes/admin/api-auth.php:426
282
- msgid "Cannot deauthenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings."
 
 
283
  msgstr ""
284
 
285
- #: includes/admin/api-auth.php:433
286
- msgid "Successfully deauthenticated."
287
  msgstr ""
288
 
289
- #: includes/admin/api-auth.php:436
290
- msgid "Successfully force deauthenticated."
291
  msgstr ""
292
 
293
- #: includes/admin/api-auth.php:438
294
- msgid "Could not deauthenticate."
295
  msgstr ""
296
 
297
- #: includes/admin/common.php:754
298
- msgid "MonsterInsights has detected that it's files are being blocked. This is usually caused by a adblock browser plugin (particularly uBlock Origin), or a conflicting WordPress theme or plugin. This issue only affects the admin side of MonsterInsights. To solve this, ensure MonsterInsights is whitelisted for your website URL in any adblock browser plugin you use. For step by step directions on how to do this, %1$sclick here%2$s. If this doesn't solve the issue (rare), send us a ticket %3$shere%2$s and we'll be happy to help diagnose the issue."
299
  msgstr ""
300
 
301
- #: includes/admin/licensing/license-actions.php:117
302
- msgid "Please enter a license key."
 
303
  msgstr ""
304
 
305
- #: includes/admin/licensing/license-actions.php:125
306
- msgid "You are not allowed to verify a license key."
 
307
  msgstr ""
308
 
309
- #: includes/admin/licensing/license-actions.php:137
310
- #: includes/admin/licensing/license-actions.php:186
311
- #: includes/admin/licensing/license-actions.php:273
312
- #: includes/admin/licensing/license-actions.php:386
313
- #: includes/admin/licensing/license-actions.php:421
314
- msgid "There was an error connecting to the remote key API. Please try again later."
315
  msgstr ""
316
 
317
- #: includes/admin/licensing/license-actions.php:163
318
- #: includes/admin/licensing/license-actions.php:205
319
- msgid "Congratulations! This site is now receiving automatic updates."
320
  msgstr ""
321
 
322
- #: includes/admin/licensing/license-actions.php:317
323
- msgid "Congratulations! Your key has been refreshed successfully."
324
  msgstr ""
325
 
326
- #: includes/admin/licensing/license-actions.php:368
327
- msgid "Please refresh the page and try again."
328
  msgstr ""
329
 
330
- #: includes/admin/licensing/license-actions.php:376
331
- msgid "You are not allowed to deactivate the license key."
332
  msgstr ""
333
 
334
- #: includes/admin/licensing/license-actions.php:404
335
- #: includes/admin/licensing/license-actions.php:434
336
- msgid "Congratulations! You have deactivated the key from this site successfully."
337
  msgstr ""
338
 
339
- #: includes/admin/licensing/skin.php:86
340
- msgid "There was an error installing the addon. Please try again."
 
341
  msgstr ""
342
 
343
- #. Translators: First one is a link to the settings page, second one is closing tag, third is a link to MonsterInsights.com
344
- #: includes/admin/licensing/updater.php:151
345
- msgid "In order to enable updates, you need to have a valid license key on the %1$ssettings page%2$s. If your license key is expired or you need a new key, then %3$sclick here to purchase MonsterInsights Pro%2$s."
346
  msgstr ""
347
 
348
  #: includes/admin/notice.php:225
@@ -357,26 +682,35 @@ msgstr ""
357
  msgid "There seems to be an issue running JavaScript on your website, which MonsterInsights is crafted in to give you the best experience possible."
358
  msgstr ""
359
 
360
- #: includes/admin/pages/settings.php:102
 
 
 
 
361
  msgid "Copy the error message above and paste it in a message to the MonsterInsights support team."
362
  msgstr ""
363
 
364
- #: includes/admin/pages/settings.php:105
365
  msgid "Resolve This Issue"
366
  msgstr ""
367
 
368
- #: includes/admin/pages/settings.php:109
369
  msgid "Your browser version is not supported"
370
  msgstr ""
371
 
372
- #: includes/admin/pages/settings.php:110
373
  msgid "You are using a browser which is no longer supported by MonsterInsights. Please update or use another browser in order to access the plugin settings."
374
  msgstr ""
375
 
376
- #: includes/admin/pages/settings.php:112
377
  msgid "View supported browsers"
378
  msgstr ""
379
 
 
 
 
 
 
380
  #: includes/admin/reports/abstract-report.php:54
381
  msgid "Access denied"
382
  msgstr ""
@@ -401,181 +735,76 @@ msgstr ""
401
  msgid "The Google oAuth authentication needs to be re-authenticated to view data."
402
  msgstr ""
403
 
404
- #: includes/admin/reports/abstract-report.php:120
405
  msgid "No data found"
406
  msgstr ""
407
 
408
- #: includes/admin/reports/abstract-report.php:166
409
  msgid "Invalid date range."
410
  msgstr ""
411
 
412
- #: includes/admin/reports/abstract-report.php:267
413
  msgid "You must authenticate with MonsterInsights to use reports."
414
  msgstr ""
415
 
416
- #: includes/admin/reports/abstract-report.php:316
417
  msgid "You currently have a %s level license, but this report requires at least a %s level license to view the %s. Please upgrade to view this report."
418
  msgstr ""
419
 
420
- #: includes/admin/reports/abstract-report.php:328
421
  msgid "Ready to Get Analytics Super-Powers?"
422
  msgstr ""
423
 
424
- #: includes/admin/reports/abstract-report.php:330
425
  msgid "(And Crush Your Competition?)"
426
  msgstr ""
427
 
428
- #: includes/admin/reports/abstract-report.php:333
429
  msgid ""
430
- "Hey there! It looks like you've got the %s license installed on your site.
431
  "\t\t\t\t\t\t\t\t\t That's awesome! %s"
432
  msgstr ""
433
 
434
- #: includes/admin/reports/abstract-report.php:336
435
  msgid "Do you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with the %s level%s of our paid packages. You'll need to upgrade your license to get instant access."
436
  msgstr ""
437
 
438
- #: includes/admin/reports/abstract-report.php:338
439
  msgid "It's easy! To upgrade, navigate to %sMy Account%s on MonsterInsights.com, go to the licenses tab, and click upgrade. We also have a %sstep by step guide%s with pictures of this process."
440
  msgstr ""
441
 
442
- #: includes/admin/reports/abstract-report.php:340
443
- #: includes/admin/reports/abstract-report.php:349
444
  msgid "If you have any questions, don't hesitate to reach out. We're here to help."
445
  msgstr ""
446
 
447
- #: includes/admin/reports/abstract-report.php:342
448
  msgid ""
449
- "Hey there! %s It looks like you've got the free version of MonsterInsights installed on your site.
450
  "\t\t\t\t\t\t\t\t\t That's awesome!"
451
  msgstr ""
452
 
453
- #: includes/admin/reports/abstract-report.php:345
454
  msgid "Do you you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with %s level%s of our paid packages. To get instant access, you'll want to buy a MonsterInsights license, which also gives you access to powerful addons, expanded reporting (including the ability to use custom date ranges), comprehensive tracking features (like UserID tracking) and access to our world-class support team."
455
  msgstr ""
456
 
457
- #: includes/admin/reports/abstract-report.php:347
458
  msgid "Upgrading is easy! To upgrade, navigate to %sour pricing page%s, purchase the required license, and then follow the %sinstructions in the email receipt%s to upgrade. It only takes a few minutes to unlock the most powerful, yet easy to use analytics tracking system for WordPress."
459
  msgstr ""
460
 
461
- #: includes/admin/reports/abstract-report.php:355
462
- #: languages/vue.php:1323
463
  msgid "Upgrade Now"
464
  msgstr ""
465
 
466
- #: includes/admin/reports/abstract-report.php:391
467
  msgid "Visit addons page"
468
  msgstr ""
469
 
470
- #: includes/admin/reports/abstract-report.php:393
471
  msgid "Please ask your webmaster to enable this addon."
472
  msgstr ""
473
 
474
- #: includes/admin/reports/overview.php:34
475
- #: languages/vue.php:209
476
- msgid "Overview"
477
- msgstr ""
478
-
479
- #: includes/admin/review.php:98
480
- msgid "Are you enjoying MonsterInsights?"
481
- msgstr ""
482
-
483
- #: includes/admin/review.php:100
484
- msgid "Yes"
485
- msgstr ""
486
-
487
- #: includes/admin/review.php:101
488
- msgid "Not Really"
489
- msgstr ""
490
-
491
- #: includes/admin/review.php:105
492
- msgid "We're sorry to hear you aren't enjoying MonsterInsights. We would love a chance to improve. Could you take a minute and let us know what we can do better?"
493
- msgstr ""
494
-
495
- #: includes/admin/review.php:107
496
- msgid "Give Feedback"
497
- msgstr ""
498
-
499
- #: includes/admin/review.php:108
500
- msgid "No thanks"
501
- msgstr ""
502
-
503
- #: includes/admin/review.php:112
504
- msgid "That’s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?"
505
- msgstr ""
506
-
507
- #: includes/admin/review.php:113
508
- msgid "~ Syed Balkhi<br>Co-Founder of MonsterInsights"
509
- msgstr ""
510
-
511
- #: includes/admin/review.php:115
512
- msgid "Ok, you deserve it"
513
- msgstr ""
514
-
515
- #: includes/admin/review.php:116
516
- msgid "Nope, maybe later"
517
- msgstr ""
518
-
519
- #: includes/admin/review.php:117
520
- msgid "I already did"
521
- msgstr ""
522
-
523
- #: includes/admin/routes.php:270
524
- msgid "The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!"
525
- msgstr ""
526
-
527
- #: includes/admin/routes.php:279
528
- msgid "Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers."
529
- msgstr ""
530
-
531
- #: includes/admin/routes.php:289
532
- msgid "SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. SMTP helps increase email deliverability by using proper authentication"
533
- msgstr ""
534
-
535
- #: includes/admin/routes.php:409
536
- msgid "Invalid UA code"
537
- msgstr ""
538
-
539
- #: includes/admin/routes.php:436
540
- msgid "Please upload a valid .json file"
541
- msgstr ""
542
-
543
- #: includes/admin/routes.php:445
544
- msgid "Please upload a file to import"
545
- msgstr ""
546
-
547
- #: includes/admin/routes.php:496
548
- msgid "You don't have permission to view MonsterInsights reports."
549
- msgstr ""
550
-
551
- #: includes/admin/routes.php:508
552
- msgid "You can't view MonsterInsights reports because you are not licensed."
553
- msgstr ""
554
-
555
- #: includes/admin/routes.php:509
556
- msgid "Add your license"
557
- msgstr ""
558
-
559
- #: includes/admin/routes.php:516
560
- msgid "You can't view MonsterInsights reports due to license key errors."
561
- msgstr ""
562
-
563
- #: includes/admin/routes.php:524
564
- msgid "You must authenticate with MonsterInsights before you can view reports."
565
- msgstr ""
566
-
567
- #: includes/admin/routes.php:530
568
- msgid "Unknown report. Try refreshing and retrying. Contact support if this issue persists."
569
- msgstr ""
570
-
571
- #: includes/admin/routes.php:566
572
- msgid "We encountered an error when fetching the report data."
573
- msgstr ""
574
-
575
- #: includes/admin/tracking.php:242
576
- msgid "Once Weekly"
577
- msgstr ""
578
-
579
  #: includes/api-request.php:191
580
  msgid "The firewall of your server is blocking outbound calls. Please contact your hosting provider to fix this issue. %s"
581
  msgstr ""
@@ -618,38 +847,6 @@ msgstr ""
618
  msgid "Reason: The API was unreachable because no external hosts are allowed on this site."
619
  msgstr ""
620
 
621
- #: includes/deprecated.php:126
622
- msgid "%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s!"
623
- msgstr ""
624
-
625
- #: includes/deprecated.php:179
626
- msgid "%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s."
627
- msgstr ""
628
-
629
- #: includes/frontend/tracking/class-tracking-analytics.php:218
630
- msgid "Note: MonsterInsights is not currently configured on this site. The site owner needs to authenticate with Google Analytics in the MonsterInsights settings panel."
631
- msgstr ""
632
-
633
- #: includes/frontend/tracking/class-tracking-analytics.php:221
634
- msgid "Note: MonsterInsights does not track you as a logged in site administrator to prevent site owners from accidentally skewing their own Google Analytics data."
635
- msgstr ""
636
-
637
- #: includes/frontend/tracking/class-tracking-analytics.php:224
638
- msgid "Note: The site owner has disabled Google Analytics tracking for your user role."
639
- msgstr ""
640
-
641
- #: includes/frontend/tracking/class-tracking-analytics.php:300
642
- msgid "Not running function"
643
- msgstr ""
644
-
645
- #: includes/frontend/tracking/class-tracking-analytics.php:300
646
- msgid "because you are not being tracked."
647
- msgstr ""
648
-
649
- #: includes/frontend/tracking/class-tracking-preview.php:77
650
- msgid "You are currently in a preview window. MonsterInsights doesn't track preview window traffic to avoid false visit reports."
651
- msgstr ""
652
-
653
  #: includes/helpers.php:366
654
  msgid "United States"
655
  msgstr ""
@@ -1658,6 +1855,24 @@ msgstr ""
1658
  msgid "Zimbabwe"
1659
  msgstr ""
1660
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1661
  #: languages/vue.php:5
1662
  msgid "Refreshing Report"
1663
  msgstr ""
@@ -1854,63 +2069,63 @@ msgstr ""
1854
  msgid "Get Fresh Reports Data Every 60 Seconds"
1855
  msgstr ""
1856
 
1857
- #: languages/vue.php:152
1858
  msgid "Overview Report"
1859
  msgstr ""
1860
 
1861
- #: languages/vue.php:155
1862
  msgid "Loading Settings"
1863
  msgstr ""
1864
 
1865
- #: languages/vue.php:158
1866
  msgid "Saving Changes..."
1867
  msgstr ""
1868
 
1869
- #: languages/vue.php:161
1870
  msgid "Settings Updated"
1871
  msgstr ""
1872
 
1873
- #: languages/vue.php:164
1874
  msgid "Could Not Save Changes"
1875
  msgstr ""
1876
 
1877
- #: languages/vue.php:170
1878
  msgid "Congratulations! "
1879
  msgstr ""
1880
 
1881
- #: languages/vue.php:173
1882
  msgid "You Successfully Unlocked the most powerful Analytics plugin"
1883
  msgstr ""
1884
 
1885
- #: languages/vue.php:176
1886
  msgid "Publishers Report"
1887
  msgstr ""
1888
 
1889
- #: languages/vue.php:179
1890
  msgid "eCommerce Report"
1891
  msgstr ""
1892
 
1893
- #: languages/vue.php:182
1894
  msgid "Search Console Report"
1895
  msgstr ""
1896
 
1897
- #: languages/vue.php:185
1898
  msgid "Dimensions Report"
1899
  msgstr ""
1900
 
1901
- #: languages/vue.php:188
1902
  msgid "Forms Report"
1903
  msgstr ""
1904
 
1905
- #: languages/vue.php:191
1906
  msgid "Real-Time Report"
1907
  msgstr ""
1908
 
1909
- #: languages/vue.php:194
1910
  msgid "Recommended Plugin: %s"
1911
  msgstr ""
1912
 
1913
- #: languages/vue.php:198
1914
  msgid "Install"
1915
  msgstr ""
1916
 
@@ -1922,40 +2137,15 @@ msgstr ""
1922
  msgid "Learn More"
1923
  msgstr ""
1924
 
1925
- #: languages/vue.php:212
1926
- #: lite/includes/admin/reports/report-publisher.php:22
1927
- msgid "Publishers"
1928
- msgstr ""
1929
-
1930
- #: languages/vue.php:216
1931
- #: lite/includes/admin/reports/report-ecommerce.php:22
1932
- msgid "eCommerce"
1933
- msgstr ""
1934
-
1935
- #: languages/vue.php:219
1936
- #: lite/includes/admin/reports/report-queries.php:22
1937
- msgid "Search Console"
1938
- msgstr ""
1939
-
1940
- #: languages/vue.php:222
1941
- #: lite/includes/admin/reports/report-dimensions.php:22
1942
- msgid "Dimensions"
1943
- msgstr ""
1944
-
1945
- #: languages/vue.php:225
1946
- #: lite/includes/admin/reports/report-forms.php:22
1947
- msgid "Forms"
1948
- msgstr ""
1949
-
1950
- #: languages/vue.php:228
1951
  msgid "Real-Time"
1952
  msgstr ""
1953
 
1954
- #: languages/vue.php:231
1955
  msgid "Loading settings"
1956
  msgstr ""
1957
 
1958
- #: languages/vue.php:237
1959
  msgid "Getting Started"
1960
  msgstr ""
1961
 
@@ -1963,2184 +2153,2157 @@ msgstr ""
1963
  msgid "Lite vs Pro"
1964
  msgstr ""
1965
 
1966
- #: languages/vue.php:244
1967
  msgid "General"
1968
  msgstr ""
1969
 
1970
- #: languages/vue.php:248
1971
  msgid "Engagement"
1972
  msgstr ""
1973
 
1974
- #: languages/vue.php:252
1975
  msgid "Publisher"
1976
  msgstr ""
1977
 
1978
- #: languages/vue.php:256
1979
  msgid "Conversions"
1980
  msgstr ""
1981
 
1982
- #: languages/vue.php:260
1983
  msgid "Advanced"
1984
  msgstr ""
1985
 
1986
- #: languages/vue.php:263
1987
  msgid "URL Builder"
1988
  msgstr ""
1989
 
1990
- #: languages/vue.php:266
1991
  msgid "Import Export"
1992
  msgstr ""
1993
 
1994
- #: languages/vue.php:269
1995
  msgid "Time to Purchase"
1996
  msgstr ""
1997
 
1998
- #: languages/vue.php:272
1999
  msgid "This list shows how many days from first visit it took users to purchase products from your site."
2000
  msgstr ""
2001
 
2002
- #: languages/vue.php:275
2003
  msgid "Sessions to Purchase"
2004
  msgstr ""
2005
 
2006
- #: languages/vue.php:278
2007
  msgid "This list shows the number of sessions it took users before they purchased a product from your website."
2008
  msgstr ""
2009
 
2010
- #: languages/vue.php:281
2011
  msgid "Top Posts/Pages"
2012
  msgstr ""
2013
 
2014
- #: languages/vue.php:284
2015
  msgid "This list shows the most viewed posts and pages on your website."
2016
  msgstr ""
2017
 
2018
- #: languages/vue.php:287
2019
  msgid "New vs. Returning Visitors"
2020
  msgstr ""
2021
 
2022
- #: languages/vue.php:290
2023
  msgid "This graph shows what percent of your user sessions come from new versus repeat visitors."
2024
  msgstr ""
2025
 
2026
- #: languages/vue.php:293
2027
  msgid "Device Breakdown"
2028
  msgstr ""
2029
 
2030
- #: languages/vue.php:296
2031
  msgid "This graph shows what percent of your visitor sessions are done using a traditional computer or laptop, tablet or mobile device to view your site."
2032
  msgstr ""
2033
 
2034
- #: languages/vue.php:299
2035
  msgid "Top Landing Pages"
2036
  msgstr ""
2037
 
2038
- #: languages/vue.php:302
2039
  msgid "This list shows the top pages users first land on when visiting your website."
2040
  msgstr ""
2041
 
2042
- #: languages/vue.php:305
2043
  msgid "Top Exit Pages"
2044
  msgstr ""
2045
 
2046
- #: languages/vue.php:308
2047
  msgid "This list shows the top pages users exit your website from."
2048
  msgstr ""
2049
 
2050
- #: languages/vue.php:311
2051
  msgid "Top Outbound Links"
2052
  msgstr ""
2053
 
2054
- #: languages/vue.php:314
2055
  msgid "This list shows the top links clicked on your website that go to another website."
2056
  msgstr ""
2057
 
2058
- #: languages/vue.php:317
2059
  msgid "Top Affiliate Links"
2060
  msgstr ""
2061
 
2062
- #: languages/vue.php:320
2063
  msgid "This list shows the top affiliate links your visitors clicked on."
2064
  msgstr ""
2065
 
2066
- #: languages/vue.php:323
2067
  msgid "Top Download Links"
2068
  msgstr ""
2069
 
2070
- #: languages/vue.php:326
2071
  msgid "This list shows the download links your visitors clicked the most."
2072
  msgstr ""
2073
 
2074
- #: languages/vue.php:329
2075
  msgid "Top Products"
2076
  msgstr ""
2077
 
2078
- #: languages/vue.php:332
2079
  msgid "This list shows the top selling products on your website."
2080
  msgstr ""
2081
 
2082
- #: languages/vue.php:335
2083
  msgid "Top Conversion Sources"
2084
  msgstr ""
2085
 
2086
- #: languages/vue.php:338
2087
  msgid "This list shows the top referral websites in terms of product revenue."
2088
  msgstr ""
2089
 
2090
- #: languages/vue.php:341
2091
  msgid "Total Add/Remove"
2092
  msgstr ""
2093
 
2094
- #: languages/vue.php:344
2095
  msgid "Exit Setup"
2096
  msgstr ""
2097
 
2098
- #: languages/vue.php:347
2099
  msgid "Yikes! PHP Update Required"
2100
  msgstr ""
2101
 
2102
- #: languages/vue.php:350
2103
  msgid "MonsterInsights has detected that your site is running an outdated, insecure version of PHP (%s), which could be putting your site at risk for being hacked. WordPress itself will stop supporting your PHP version in April, 2019. Updating to the recommended version (PHP %s) only takes a few minutes and will make your website significantly faster and more secure."
2104
  msgstr ""
2105
 
2106
- #: languages/vue.php:353
2107
  msgid "Learn more about updating PHP"
2108
  msgstr ""
2109
 
2110
- #: languages/vue.php:356
2111
  msgid "Yikes! WordPress Update Required"
2112
  msgstr ""
2113
 
2114
- #: languages/vue.php:359
2115
  msgid "MonsterInsights has detected that your site is running an outdated version of WordPress (%s). MonsterInsights will stop supporting WordPress versions lower than 4.6 in April, 2019. Updating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install."
2116
  msgstr ""
2117
 
2118
- #: languages/vue.php:362
2119
  msgid "Learn more about updating WordPress"
2120
  msgstr ""
2121
 
2122
- #: languages/vue.php:365
2123
  msgid "Powered by MonsterInsights"
2124
  msgstr ""
2125
 
2126
- #: languages/vue.php:368
2127
  msgid "Save Changes"
2128
  msgstr ""
2129
 
2130
- #: languages/vue.php:371
2131
  msgid "New"
2132
  msgstr ""
2133
 
2134
- #: languages/vue.php:374
2135
  msgid "Returning"
2136
  msgstr ""
2137
 
2138
- #: languages/vue.php:377
2139
  msgid "Desktop"
2140
  msgstr ""
2141
 
2142
- #: languages/vue.php:380
2143
  msgid "Tablet"
2144
  msgstr ""
2145
 
2146
- #: languages/vue.php:383
2147
  msgid "Mobile"
2148
  msgstr ""
2149
 
2150
- #: languages/vue.php:386
2151
  msgid "Sessions"
2152
  msgstr ""
2153
 
2154
- #: languages/vue.php:389
2155
  msgid "Unique %s Sessions"
2156
  msgstr ""
2157
 
2158
- #: languages/vue.php:392
2159
  msgid "Pageviews"
2160
  msgstr ""
2161
 
2162
- #: languages/vue.php:395
2163
  msgid "Unique %s Pageviews"
2164
  msgstr ""
2165
 
2166
- #: languages/vue.php:398
2167
  msgid "Avg. Session Duration"
2168
  msgstr ""
2169
 
2170
- #: languages/vue.php:401
2171
  msgid "Bounce Rate"
2172
  msgstr ""
2173
 
2174
- #: languages/vue.php:404
2175
  msgid "Top 10 Countries"
2176
  msgstr ""
2177
 
2178
- #: languages/vue.php:407
2179
  msgid "View Countries Report"
2180
  msgstr ""
2181
 
2182
- #: languages/vue.php:410
2183
  msgid "Top 10 Referrals"
2184
  msgstr ""
2185
 
2186
- #: languages/vue.php:413
2187
  msgid "View All Referral Sources"
2188
  msgstr ""
2189
 
2190
- #: languages/vue.php:416
2191
  msgid "View Full Posts/Pages Report"
2192
  msgstr ""
2193
 
2194
- #: languages/vue.php:419
2195
  msgid "A session is the browsing session of a single user to your site."
2196
  msgstr ""
2197
 
2198
- #: languages/vue.php:422
2199
  msgid "A pageview is defined as a view of a page on your site that is being tracked by the Analytics tracking code. Each refresh of a page is also a new pageview."
2200
  msgstr ""
2201
 
2202
- #: languages/vue.php:425
2203
  msgid "Total duration of all sessions (in seconds) / number of sessions."
2204
  msgstr ""
2205
 
2206
- #: languages/vue.php:428
2207
  msgid "Percentage of single-page visits (or web sessions). It is the number of visits in which a person leaves your website from the landing page without browsing any further."
2208
  msgstr ""
2209
 
2210
- #: languages/vue.php:431
2211
  msgid "This list shows the top countries your website visitors are from."
2212
  msgstr ""
2213
 
2214
- #: languages/vue.php:434
2215
  msgid "This list shows the top websites that send your website traffic, known as referral traffic."
2216
  msgstr ""
2217
 
2218
- #: languages/vue.php:437
2219
  msgid "MonsterInsights Addons"
2220
  msgstr ""
2221
 
2222
- #: languages/vue.php:440
2223
  msgid "Search Addons"
2224
  msgstr ""
2225
 
2226
- #: languages/vue.php:443
2227
  msgid "Yes (recommended) %s- Get the latest features, bugfixes, and security updates as they are released.%s"
2228
  msgstr ""
2229
 
2230
- #: languages/vue.php:446
2231
  msgid "Minor only %s- Get bugfixes and security updates, but not major features.%s"
2232
  msgstr ""
2233
 
2234
- #: languages/vue.php:449
2235
  msgid "None %s- Manually update everything.%s"
2236
  msgstr ""
2237
 
2238
- #: languages/vue.php:452
2239
  msgid "License Key"
2240
  msgstr ""
2241
 
2242
- #: languages/vue.php:455
2243
  msgid "Google Authentication"
2244
  msgstr ""
2245
 
2246
- #: languages/vue.php:458
2247
  msgid "Connect Google Analytics + WordPress"
2248
  msgstr ""
2249
 
2250
- #: languages/vue.php:461
2251
  msgid "You will be taken to the MonsterInsights website where you'll need to connect your Analytics account."
2252
  msgstr ""
2253
 
2254
- #: languages/vue.php:464
2255
  msgid "Automatic Updates"
2256
  msgstr ""
2257
 
2258
- #: languages/vue.php:467
2259
  msgid "Setup Wizard"
2260
  msgstr ""
2261
 
2262
- #: languages/vue.php:470
2263
  msgid "Use our configuration wizard to properly setup Google Analytics with WordPress (with just a few clicks)."
2264
  msgstr ""
2265
 
2266
- #: languages/vue.php:473
2267
  msgid "Launch Setup Wizard"
2268
  msgstr ""
2269
 
2270
- #: languages/vue.php:476
2271
  msgid "Path (example: %s)"
2272
  msgstr ""
2273
 
2274
- #: languages/vue.php:479
2275
  msgid "Path has to start with a / and have no spaces"
2276
  msgstr ""
2277
 
2278
- #: languages/vue.php:482
2279
  msgid "Label (example: %s)"
2280
  msgstr ""
2281
 
2282
- #: languages/vue.php:485
2283
  msgid "Label can't contain any spaces"
2284
  msgstr ""
2285
 
2286
- #: languages/vue.php:488
2287
  msgid "Affiliate Links"
2288
  msgstr ""
2289
 
2290
- #: languages/vue.php:491
2291
  msgid "This allows you to track custom affiliate links. A path of /go/ would match urls that start with that. The label is appended onto the end of the string \"outbound-link-\", to provide unique labels for these links in Google Analytics. Complete documentation on affiliate links is available %shere%s."
2292
  msgstr ""
2293
 
2294
- #: languages/vue.php:494
2295
  msgid "Our affiliate link tracking works by setting path for internal links to track as outbound links."
2296
  msgstr ""
2297
 
2298
- #: languages/vue.php:497
2299
  msgid "Demographics"
2300
  msgstr ""
2301
 
2302
- #: languages/vue.php:500
2303
  msgid "Enable Demographics and Interests Reports for Remarketing and Advertising"
2304
  msgstr ""
2305
 
2306
- #: languages/vue.php:503
2307
  msgid "Anonymize IP Addresses"
2308
  msgstr ""
2309
 
2310
- #: languages/vue.php:506
2311
  msgid "Link Attribution"
2312
  msgstr ""
2313
 
2314
- #: languages/vue.php:509
2315
  msgid "Enable Enhanced Link Attribution"
2316
  msgstr ""
2317
 
2318
- #: languages/vue.php:512
2319
  msgid "Enable Anchor Tracking"
2320
  msgstr ""
2321
 
2322
- #: languages/vue.php:515
2323
  msgid "Enable allowAnchor"
2324
  msgstr ""
2325
 
2326
- #: languages/vue.php:518
2327
  msgid "Enable allowLinker"
2328
  msgstr ""
2329
 
2330
- #: languages/vue.php:521
2331
  msgid "Enable Tag Links in RSS"
2332
  msgstr ""
2333
 
2334
- #: languages/vue.php:524
2335
  msgid "File Downloads"
2336
  msgstr ""
2337
 
2338
- #: languages/vue.php:527
2339
  msgid "Extensions of Files to Track as Downloads"
2340
  msgstr ""
2341
 
2342
- #: languages/vue.php:530
2343
  msgid "MonsterInsights will send an event to Google Analytics if a link to a file has one of the above extensions."
2344
  msgstr ""
2345
 
2346
- #: languages/vue.php:533
2347
  msgid "Enable this setting to add the Demographics and Remarketing features to your Google Analytics tracking code. Make sure to enable Demographics and Remarketing in your Google Analytics account. We have a guide for how to do that in our %sknowledge base%s. For more information about Remarketing, we refer you to %sGoogle's documentation%s. Note that usage of this function is affected by privacy and cookie laws around the world. Be sure to follow the laws that affect your target audience."
2348
  msgstr ""
2349
 
2350
- #: languages/vue.php:536
2351
  msgid "This adds %sanonymizeIp%s, telling Google Analytics to anonymize the information sent by the tracker objects by removing the last octet of the IP address prior to its storage."
2352
  msgstr ""
2353
 
2354
- #: languages/vue.php:539
2355
  msgid "Add %sEnhanced Link Attribution%s to your tracking code."
2356
  msgstr ""
2357
 
2358
- #: languages/vue.php:542
2359
  msgid "Many WordPress \"1-page\" style themes rely on anchor tags for navigation to show virtual pages. The problem is that to Google Analytics, these are all just a single page, and it makes it hard to get meaningful statistics about pages viewed. This feature allows proper tracking in those themes."
2360
  msgstr ""
2361
 
2362
- #: languages/vue.php:545
2363
  msgid "This adds %sallowAnchor%s to the create command of the pageview hit tracking code, and makes RSS link tagging use a # as well."
2364
  msgstr ""
2365
 
2366
- #: languages/vue.php:548
2367
  msgid "Enabling %scross-domain tracking (additional setup required)%s allows you to track users across multiple properties you own (such as example-1.com and example-2.com as a single session. It also allows you fix an issue so that when a user has to go to an off-site hosted payment gateway to finish a purchase it doesn't count it as referral traffic from that gateway but maintains the visit as part of the same session.) It is required that the other site includes a Google Analytics tracker with the same UA Code."
2368
  msgstr ""
2369
 
2370
- #: languages/vue.php:551
2371
  msgid "Do not use this feature if you use FeedBurner, as FeedBurner can do this automatically and better than this plugin can. Check this %shelp page%s for info on how to enable this feature in FeedBurner."
2372
  msgstr ""
2373
 
2374
- #: languages/vue.php:554
2375
  msgid "Add domain"
2376
  msgstr ""
2377
 
2378
- #: languages/vue.php:557
2379
  msgid "Domain (example: %s)"
2380
  msgstr ""
2381
 
2382
- #: languages/vue.php:560
2383
  msgid "Please enter domain names only ( example: example.com not http://example.com ) and not current site domain ( %s )."
2384
  msgstr ""
2385
 
2386
- #: languages/vue.php:563
2387
  msgid "Cross Domain Tracking"
2388
  msgstr ""
2389
 
2390
- #: languages/vue.php:566
2391
  msgid "Cross domain tracking makes it possible for Analytics to see sessions on two related sites as a single session. More info on specific setup steps can be found in our %sknowledge base%s."
2392
  msgstr ""
2393
 
2394
- #: languages/vue.php:569
2395
  msgid "It looks like you added a Google Analytics tracking code in the custom code area, this can potentially prevent proper tracking. If you want to use a manual UA please use the setting in the %sGeneral%s tab."
2396
  msgstr ""
2397
 
2398
- #: languages/vue.php:572
2399
  msgid "Permissions"
2400
  msgstr ""
2401
 
2402
- #: languages/vue.php:575
2403
  msgid "Allow These User Roles to See Reports"
2404
  msgstr ""
2405
 
2406
- #: languages/vue.php:578
2407
  msgid "Users that have at least one of these roles will be able to view the reports."
2408
  msgstr ""
2409
 
2410
- #: languages/vue.php:581
2411
  msgid "Users that have at least one of these roles will be able to view the reports, along with any user with the manage_options capability."
2412
  msgstr ""
2413
 
2414
- #: languages/vue.php:584
2415
  msgid "Allow These User Roles to Save Settings"
2416
  msgstr ""
2417
 
2418
- #: languages/vue.php:587
2419
  msgid "Users that have at least one of these roles will be able to view and save the settings panel."
2420
  msgstr ""
2421
 
2422
- #: languages/vue.php:590
2423
  msgid "Users that have at least one of these roles will be able to view and save the settings panel, along with any user with the manage_options capability."
2424
  msgstr ""
2425
 
2426
- #: languages/vue.php:593
2427
  msgid "Exclude These User Roles From Tracking"
2428
  msgstr ""
2429
 
2430
- #: languages/vue.php:596
2431
  msgid "Users that have at least one of these roles will not be tracked into Google Analytics."
2432
  msgstr ""
2433
 
2434
- #: languages/vue.php:599
2435
  msgid "Performance"
2436
  msgstr ""
2437
 
2438
- #: languages/vue.php:602
2439
  msgid "Custom code"
2440
  msgstr ""
2441
 
2442
- #: languages/vue.php:605
2443
  msgid "Not for the average user: this allows you to add a line of code, to be added before the %spageview is sent%s."
2444
  msgstr ""
2445
 
2446
- #: languages/vue.php:611
2447
  msgid "You must have the \"unfiltered_html\" capability to view/edit this setting."
2448
  msgstr ""
2449
 
2450
- #: languages/vue.php:614
2451
  msgid "Hide Admin Bar Reports"
2452
  msgstr ""
2453
 
2454
- #: languages/vue.php:617
2455
  msgid "Enabled %s- Show reports and dashboard widget.%s"
2456
  msgstr ""
2457
 
2458
- #: languages/vue.php:620
2459
  msgid "Dashboard Widget Only %s- Disable reports, but show dashboard widget.%s"
2460
  msgstr ""
2461
 
2462
- #: languages/vue.php:623
2463
  msgid "Disabled %s- Hide reports and dashboard widget.%s"
2464
  msgstr ""
2465
 
2466
- #: languages/vue.php:626
2467
  msgid "Hello and welcome to MonsterInsights, the best Google Analytics plugin for WordPress. MonsterInsights shows you exactly which content gets the most visit, so you can analyze and optimize it for higher conversions."
2468
  msgstr ""
2469
 
2470
- #: languages/vue.php:629
2471
  msgid "Over the years, we found that in order to get the most out of Google Analytics, you needed a full time developer who could implement custom tracking, so that Google Analytics would integrate with things like WooCommerce, and track things which Google doesn't by default, like outbound links."
2472
  msgstr ""
2473
 
2474
- #: languages/vue.php:632
2475
  msgid "Our goal is to take the pain out of analytics, making it simple and easy, by eliminating the need to have to worry about code, putting the best reports directly into the area you already go to (your WordPress dashboard), and adding the most advanced insights and features without complicating our plugin with tons of settings. Quite simply, it should \"just work\"."
2476
  msgstr ""
2477
 
2478
- #: languages/vue.php:635
2479
  msgid "MonsterInsights is brought to you by the same team that's behind the largest WordPress resource site, WPBeginner, the most popular lead-generation software, OptinMonster, and the best WordPress forms plugin, WPForms."
2480
  msgstr ""
2481
 
2482
- #: languages/vue.php:638
2483
  msgid "Yup, we know a thing or two about building awesome products that customer love."
2484
  msgstr ""
2485
 
2486
- #: languages/vue.php:641
2487
  msgid "The MonsterInsights Team: Syed, Chris, Jay, Mircea, Sunita and Basanta"
2488
  msgstr ""
2489
 
2490
- #: languages/vue.php:644
2491
  msgid "Import/Export"
2492
  msgstr ""
2493
 
2494
- #: languages/vue.php:647
2495
  msgid "Import"
2496
  msgstr ""
2497
 
2498
- #: languages/vue.php:650
2499
  msgid "Import settings from another MonsterInsights website."
2500
  msgstr ""
2501
 
2502
- #: languages/vue.php:653
2503
  msgid "Export"
2504
  msgstr ""
2505
 
2506
- #: languages/vue.php:656
2507
  msgid "Export settings to import into another MonsterInsights install."
2508
  msgstr ""
2509
 
2510
- #: languages/vue.php:659
2511
  msgid "Import Settings"
2512
  msgstr ""
2513
 
2514
- #: languages/vue.php:662
2515
  msgid "Export Settings"
2516
  msgstr ""
2517
 
2518
- #: languages/vue.php:665
2519
  msgid "Please choose a file to import"
2520
  msgstr ""
2521
 
2522
- #: languages/vue.php:668
2523
  msgid "Use the filepicker below to select the settings export file from another site."
2524
  msgstr ""
2525
 
2526
- #: languages/vue.php:671
2527
  msgid "Use the button below to export a file with your MonsterInsights settings."
2528
  msgstr ""
2529
 
2530
- #: languages/vue.php:674
2531
  msgid "Uploading file..."
2532
  msgstr ""
2533
 
2534
- #: languages/vue.php:677
2535
  msgid "File imported"
2536
  msgstr ""
2537
 
2538
- #: languages/vue.php:680
2539
  msgid "Settings successfully updated!"
2540
  msgstr ""
2541
 
2542
- #: languages/vue.php:683
2543
  msgid "Error importing settings"
2544
  msgstr ""
2545
 
2546
- #: languages/vue.php:686
2547
  msgid "Please choose a .json file generated by a MonsterInsights settings export."
2548
  msgstr ""
2549
 
2550
- #: languages/vue.php:689
2551
  msgid "Ok"
2552
  msgstr ""
2553
 
2554
- #: languages/vue.php:692
2555
  msgid "Custom Campaign Parameters"
2556
  msgstr ""
2557
 
2558
- #: languages/vue.php:695
2559
  msgid "The URL builder helps you add parameters to your URLs you use in custom web or email ad campaigns."
2560
  msgstr ""
2561
 
2562
- #: languages/vue.php:698
2563
  msgid "A custom campaign is any ad campaign not using the AdWords auto-tagging feature. When users click one of the custom links, the unique parameters are sent to your Analytics account, so you can identify the urls that are the most effective in attracting users to your content."
2564
  msgstr ""
2565
 
2566
- #: languages/vue.php:701
2567
  msgid "Website URL %s"
2568
  msgstr ""
2569
 
2570
- #: languages/vue.php:704
2571
  msgid "The full website URL (e.g. %s %s%s)"
2572
  msgstr ""
2573
 
2574
- #: languages/vue.php:707
2575
  msgid "Campaign Source %s"
2576
  msgstr ""
2577
 
2578
- #: languages/vue.php:710
2579
  msgid "Enter a referrer (e.g. %sfacebook, newsletter, google%s)"
2580
  msgstr ""
2581
 
2582
- #: languages/vue.php:713
2583
  msgid "Enter a marketing medium (e.g. %scpc, banner, email%s)"
2584
  msgstr ""
2585
 
2586
- #: languages/vue.php:716
2587
  msgid "Enter a name to easily identify (e.g. %sspring_sale%s)"
2588
  msgstr ""
2589
 
2590
- #: languages/vue.php:719
2591
  msgid "Enter the paid keyword"
2592
  msgstr ""
2593
 
2594
- #: languages/vue.php:722
2595
  msgid "Enter something to differentiate ads"
2596
  msgstr ""
2597
 
2598
- #: languages/vue.php:725
2599
  msgid "Use Fragment"
2600
  msgstr ""
2601
 
2602
- #: languages/vue.php:728
2603
  msgid "Set the parameters in the fragment portion of the URL %s(not recommended)%s"
2604
  msgstr ""
2605
 
2606
- #: languages/vue.php:731
2607
  msgid "URL to use"
2608
  msgstr ""
2609
 
2610
- #: languages/vue.php:734
2611
  msgid "Updates automatically"
2612
  msgstr ""
2613
 
2614
- #: languages/vue.php:737
2615
  msgid "Copy to clipboard"
2616
  msgstr ""
2617
 
2618
- #: languages/vue.php:740
2619
  msgid "More Information & Examples"
2620
  msgstr ""
2621
 
2622
- #: languages/vue.php:743
2623
  msgid "The following table gives a detailed explanation and example of each of the campaign parameters."
2624
  msgstr ""
2625
 
2626
- #: languages/vue.php:746
2627
  msgid "Campaign Source"
2628
  msgstr ""
2629
 
2630
- #: languages/vue.php:749
2631
  msgid "Required. Use utm_source to identify a search engine, newsletter name, or other source."
2632
  msgstr ""
2633
 
2634
- #: languages/vue.php:752
2635
  msgid "Campaign Medium"
2636
  msgstr ""
2637
 
2638
- #: languages/vue.php:755
2639
  msgid "Use utm_medium to identify a medium such as email or cost-per-click."
2640
  msgstr ""
2641
 
2642
- #: languages/vue.php:758
2643
  msgid "Campaign Name"
2644
  msgstr ""
2645
 
2646
- #: languages/vue.php:761
2647
  msgid "Used for keyword analysis. Use utm_campaign to identify a specific product promotion or strategic campaign."
2648
  msgstr ""
2649
 
2650
- #: languages/vue.php:764
2651
  msgid "Campaign Term"
2652
  msgstr ""
2653
 
2654
- #: languages/vue.php:767
2655
  msgid "Used for paid search. Use utm_term to note the keywords for this ad."
2656
  msgstr ""
2657
 
2658
- #: languages/vue.php:770
2659
  msgid "Campaign Content"
2660
  msgstr ""
2661
 
2662
- #: languages/vue.php:773
2663
  msgid "Used for A/B testing and content-targeted ads. Use utm_content to differentiate ads or links that point to the same URL."
2664
  msgstr ""
2665
 
2666
- #: languages/vue.php:776
2667
  msgid "Example: %s"
2668
  msgstr ""
2669
 
2670
- #: languages/vue.php:779
2671
  msgid "Examples: %s"
2672
  msgstr ""
2673
 
2674
- #: languages/vue.php:782
2675
  msgid "About Campaigns"
2676
  msgstr ""
2677
 
2678
- #: languages/vue.php:785
2679
  msgid "About Custom Campaigns"
2680
  msgstr ""
2681
 
2682
- #: languages/vue.php:788
2683
  msgid "Best practices for creating Custom Campaigns"
2684
  msgstr ""
2685
 
2686
- #: languages/vue.php:791
2687
  msgid "About the Referral Traffic report"
2688
  msgstr ""
2689
 
2690
- #: languages/vue.php:794
2691
  msgid "About traffic source dimensions"
2692
  msgstr ""
2693
 
2694
- #: languages/vue.php:797
2695
  msgid "AdWords Auto-Tagging"
2696
  msgstr ""
2697
 
2698
- #: languages/vue.php:800
2699
  msgid "Additional Information"
2700
  msgstr ""
2701
 
2702
- #: languages/vue.php:803
2703
  msgid "GDPR Guide"
2704
  msgstr ""
2705
 
2706
- #: languages/vue.php:806
2707
  msgid "Compliance with European data laws including GDPR can be confusing and time-consuming. In order to help MonsterInsights users comply with these laws, we’ve created an addon that automates a lot of the necessary configuration changes for you. "
2708
  msgstr ""
2709
 
2710
- #: languages/vue.php:809
2711
  msgid "How to install and activate MonsterInsights addons"
2712
  msgstr ""
2713
 
2714
- #: languages/vue.php:812
2715
  msgid "The process for installing and activating addons is quick and easy after you install the MonsterInsights plugin. In this guide we’ll walk you through the process, step by step."
2716
  msgstr ""
2717
 
2718
- #: languages/vue.php:815
2719
  msgid "Enabling eCommerce Tracking and Reports"
2720
  msgstr ""
2721
 
2722
- #: languages/vue.php:818
2723
  msgid "Want to track your eCommerce sales data for your WooCommerce, MemberPress, or Easy Digital Downloads store with MonsterInsights? In this guide, we’ll show you how to enable eCommerce tracking in Google Analytics in just a few clicks."
2724
  msgstr ""
2725
 
2726
- #: languages/vue.php:821
2727
  msgid "Read Documentation"
2728
  msgstr ""
2729
 
2730
- #: languages/vue.php:824
2731
  msgid "Getting Started with MonsterInsights"
2732
  msgstr ""
2733
 
2734
- #: languages/vue.php:827
2735
  msgid "MonsterInsights is the easiest analytics solution on the market to get started with, as we walk you through exactly what you need to do, in plain english, using our 3 minute setup wizard."
2736
  msgstr ""
2737
 
2738
- #: languages/vue.php:830
2739
  msgid "To begin with, we’ll get your site authorized with Google Analytics, so we can start tracking and generating reports for you right away."
2740
  msgstr ""
2741
 
2742
- #: languages/vue.php:833
2743
  msgid "In no time at all, and after just a few clicks, you'll have setup the most powerful Google Analytics tracking available for WordPress. It's easy to double your traffic and sales when you know exactly how people find and use your website. Let's get started!."
2744
  msgstr ""
2745
 
2746
- #: languages/vue.php:836
2747
  msgid "Launch the wizard!"
2748
  msgstr ""
2749
 
2750
- #: languages/vue.php:839
2751
  msgid "Get MonsterInsights Pro and Unlock all the Powerful Features"
2752
  msgstr ""
2753
 
2754
- #: languages/vue.php:842
2755
  msgid "Thanks for being a loyal MonsterInsights Lite user. %sUpgrade to MonsterInsights Pro%s to unlock all the awesome features and experience why MonsterInsights is consistently rated the best Google Analytics solution for WordPress."
2756
  msgstr ""
2757
 
2758
- #: languages/vue.php:845
2759
  msgid "Universal Tracking across devices and campaigns with just a few clicks."
2760
  msgstr ""
2761
 
2762
- #: languages/vue.php:848
2763
  msgid "See your website analytics reports inside the WordPress dashboard"
2764
  msgstr ""
2765
 
2766
- #: languages/vue.php:851
2767
  msgid "Get real-time stats right inside WordPress"
2768
  msgstr ""
2769
 
2770
- #: languages/vue.php:854
2771
  msgid "1-click Google Analytics Enhanced Ecommerce tracking"
2772
  msgstr ""
2773
 
2774
- #: languages/vue.php:857
2775
  msgid "Get detailed stats for each post and page."
2776
  msgstr ""
2777
 
2778
- #: languages/vue.php:860
2779
  msgid "Automatically track clicks on your affiliate links and ads."
2780
  msgstr ""
2781
 
2782
- #: languages/vue.php:863
2783
  msgid "Make Google Analytics GDPR compliant automatically"
2784
  msgstr ""
2785
 
2786
- #: languages/vue.php:866
2787
  msgid "Setup tracking for authors, categories, tags, custom post types, users and more"
2788
  msgstr ""
2789
 
2790
- #: languages/vue.php:869
2791
  msgid "Enable Google Optimize for A/B testing, adjust sample speed & sample rate."
2792
  msgstr ""
2793
 
2794
- #: languages/vue.php:872
2795
  msgid "More advanced features"
2796
  msgstr ""
2797
 
2798
- #: languages/vue.php:875
2799
  msgid "Get MonsterInsights Pro Today and Unlock all the Powerful Features"
2800
  msgstr ""
2801
 
2802
- #: languages/vue.php:878
2803
  msgid "Bonus: MonsterInsights Lite users get %s50%% off regular price%s, automatically applied at checkout."
2804
  msgstr ""
2805
 
2806
- #: languages/vue.php:881
2807
  msgid "How to Connect to Google Analytics"
2808
  msgstr ""
2809
 
2810
- #: languages/vue.php:884
2811
  msgid "After you install MonsterInsights, you’ll need to connect your WordPress site with your Google Analytics account. MonsterInsights makes the process easy, with no coding required."
2812
  msgstr ""
2813
 
2814
- #: languages/vue.php:887
2815
  msgid "Guide and Checklist for Advanced Insights"
2816
  msgstr ""
2817
 
2818
- #: languages/vue.php:890
2819
  msgid "Our goal is to make it as easy as possible for you to measure and track your stats so you can grow your business. This easy-to-follow guide and checklist will get you set up with MonsterInsights’ advanced tracking."
2820
  msgstr ""
2821
 
2822
- #: languages/vue.php:893
2823
  msgid "WordPress Admin Area Reports"
2824
  msgstr ""
2825
 
2826
- #: languages/vue.php:896
2827
  msgid "Standard Reports"
2828
  msgstr ""
2829
 
2830
- #: languages/vue.php:899
2831
  msgid "Overview Reports for the last 30 days."
2832
  msgstr ""
2833
 
2834
- #: languages/vue.php:902
2835
  msgid "Advanced Reports"
2836
  msgstr ""
2837
 
2838
- #: languages/vue.php:905
2839
  msgid "Publisher, eCommerce, Search Console, Custom Dimensions, Forms and Real-Time with custom date period selection"
2840
  msgstr ""
2841
 
2842
- #: languages/vue.php:908
2843
  msgid "Dashboard Widget"
2844
  msgstr ""
2845
 
2846
- #: languages/vue.php:911
2847
  msgid "Basic Widget"
2848
  msgstr ""
2849
 
2850
- #: languages/vue.php:914
2851
  msgid "Overview Report Synopsis"
2852
  msgstr ""
2853
 
2854
- #: languages/vue.php:917
2855
  msgid "Advanced Dashboard Widget"
2856
  msgstr ""
2857
 
2858
- #: languages/vue.php:920
2859
  msgid "Includes the complete Overview report, Publisher reports and 6 different eCommerce reports"
2860
  msgstr ""
2861
 
2862
- #: languages/vue.php:923
2863
  msgid "Publisher Reports"
2864
  msgstr ""
2865
 
2866
- #: languages/vue.php:926
2867
  msgid "Advanced Publisher Reports & Tracking"
2868
  msgstr ""
2869
 
2870
- #: languages/vue.php:929
2871
  msgid "View Top Landing/Exit Pages, Top Links, Demographics & Interests data and more"
2872
  msgstr ""
2873
 
2874
- #: languages/vue.php:933
2875
  msgid "Custom Dimensions"
2876
  msgstr ""
2877
 
2878
- #: languages/vue.php:936
2879
  msgid "Not Available"
2880
  msgstr ""
2881
 
2882
- #: languages/vue.php:939
2883
  msgid "Complete Custom Dimensions Tracking"
2884
  msgstr ""
2885
 
2886
- #: languages/vue.php:942
2887
  msgid "Track and measure by the Author, Post Type, Category, Tags, SEO Score, Focus Keyword, Logged-in User, User ID and Published Time of each post and page"
2888
  msgstr ""
2889
 
2890
- #: languages/vue.php:948
2891
  msgid "Limited support"
2892
  msgstr ""
2893
 
2894
- #: languages/vue.php:951
2895
  msgid "Priority Support"
2896
  msgstr ""
2897
 
2898
- #: languages/vue.php:954
2899
  msgid "Get the most out of MonsterInsights by upgrading to Pro and unlocking all of the powerful features."
2900
  msgstr ""
2901
 
2902
- #: languages/vue.php:957
2903
  msgid "Feature"
2904
  msgstr ""
2905
 
2906
- #: languages/vue.php:960
2907
  msgid "Lite"
2908
  msgstr ""
2909
 
2910
- #: languages/vue.php:963
2911
  msgid "Pro"
2912
  msgstr ""
2913
 
2914
- #: languages/vue.php:966
2915
  msgid "Universal Tracking"
2916
  msgstr ""
2917
 
2918
- #: languages/vue.php:969
2919
  msgid "Included"
2920
  msgstr ""
2921
 
2922
- #: languages/vue.php:972
2923
  msgid "Custom Google Analytics Link Tracking"
2924
  msgstr ""
2925
 
2926
- #: languages/vue.php:975
2927
  msgid "Standard Tracking"
2928
  msgstr ""
2929
 
2930
- #: languages/vue.php:978
2931
  msgid "Advanced Tracking"
2932
  msgstr ""
2933
 
2934
- #: languages/vue.php:981
2935
  msgid "Automatic tracking of outbound/external, file download, affiliate, email and telephone links and our simple Custom Lin
2
  # This file is distributed under the same license as the MonsterInsights Pro plugin.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: MonsterInsights Pro 7.8.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/monsterinsights\n"
7
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
8
  "Language-Team: LANGUAGE <LL@li.org>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "POT-Creation-Date: 2019-09-10T14:43:44+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.2.0\n"
15
  "X-Domain: google-analytics-for-wordpress\n"
27
  msgstr ""
28
 
29
  #. Author of the plugin
30
+ #: lite/includes/admin/wp-site-health.php:171
31
+ #: lite/includes/admin/wp-site-health.php:223
32
+ #: lite/includes/admin/wp-site-health.php:250
33
+ #: lite/includes/admin/wp-site-health.php:288
34
+ #: lite/includes/admin/wp-site-health.php:315
35
+ #: lite/includes/admin/wp-site-health.php:342
36
+ #: lite/includes/admin/wp-site-health.php:367
37
+ #: lite/includes/admin/wp-site-health.php:406
38
+ #: lite/includes/admin/dashboard-widget.php:90
39
  #: includes/admin/admin.php:38
40
  #: includes/admin/admin.php:41
41
  #: includes/admin/admin.php:51
 
 
 
 
 
 
 
 
42
  msgid "MonsterInsights"
43
  msgstr ""
44
 
46
  msgid "https://www.monsterinsights.com/?utm_source=proplugin&utm_medium=pluginheader&utm_campaign=authoruri&utm_content=7%2E0%2E0"
47
  msgstr ""
48
 
49
+ #: lite/includes/admin/wp-site-health.php:53
50
+ msgid "MonsterInsights Authentication"
 
51
  msgstr ""
52
 
53
+ #: lite/includes/admin/wp-site-health.php:58
54
+ msgid "MonsterInsights Automatic Updates"
55
  msgstr ""
56
 
57
+ #: lite/includes/admin/wp-site-health.php:64
58
+ msgid "MonsterInsights eCommerce"
59
  msgstr ""
60
 
61
+ #: lite/includes/admin/wp-site-health.php:71
62
+ msgid "MonsterInsights AMP"
 
 
 
 
63
  msgstr ""
64
 
65
+ #: lite/includes/admin/wp-site-health.php:78
66
+ msgid "MonsterInsights FBIA"
 
 
67
  msgstr ""
68
 
69
+ #: lite/includes/admin/wp-site-health.php:84
70
+ msgid "MonsterInsights Connection"
71
  msgstr ""
72
 
73
+ #: lite/includes/admin/wp-site-health.php:168
74
+ msgid "Your website is authenticated with MonsterInsights"
 
 
75
  msgstr ""
76
 
77
+ #: lite/includes/admin/wp-site-health.php:174
78
+ msgid "MonsterInsights integrates your WordPress website with Google Analytics."
 
 
79
  msgstr ""
80
 
81
+ #: lite/includes/admin/wp-site-health.php:178
82
+ #: languages/vue.php:1817
83
+ msgid "View Reports"
84
  msgstr ""
85
 
86
+ #: lite/includes/admin/wp-site-health.php:189
87
+ msgid "You are using Manual UA code output"
88
  msgstr ""
89
 
90
+ #: lite/includes/admin/wp-site-health.php:190
91
+ msgid "We highly recommend authenticating with MonsterInsights so that you can access our new reporting area and take advantage of new MonsterInsights features."
 
92
  msgstr ""
93
 
94
+ #: lite/includes/admin/wp-site-health.php:194
95
+ #: lite/includes/admin/wp-site-health.php:205
96
+ msgid "Authenticate now"
97
  msgstr ""
98
 
99
+ #: lite/includes/admin/wp-site-health.php:200
100
+ msgid "Please configure your Google Analytics settings"
101
  msgstr ""
102
 
103
+ #: lite/includes/admin/wp-site-health.php:201
104
+ msgid "Your traffic is not being tracked by MonsterInsights at the moment and you are losing data. Authenticate and get access to the reporting area and advanced tracking features."
 
105
  msgstr ""
106
 
107
+ #: lite/includes/admin/wp-site-health.php:227
108
+ msgid "MonsterInsights Upgrade not applied"
 
109
  msgstr ""
110
 
111
+ #: lite/includes/admin/wp-site-health.php:228
112
+ msgid "A valid license has been added to MonsterInsights but you are still using the Lite version."
113
  msgstr ""
114
 
115
+ #: lite/includes/admin/wp-site-health.php:232
116
+ msgid "Go to License Settings"
117
  msgstr ""
118
 
119
+ #: lite/includes/admin/wp-site-health.php:247
120
+ msgid "Your website is receiving automatic updates"
121
  msgstr ""
122
 
123
+ #: lite/includes/admin/wp-site-health.php:253
124
+ msgid "MonsterInsights automatic updates are enabled and you are getting the latest features, bugfixes, and security updates as they are released."
 
125
  msgstr ""
126
 
127
+ #: lite/includes/admin/wp-site-health.php:260
128
+ msgid "Your website is receiving minor updates"
 
 
129
  msgstr ""
130
 
131
+ #: lite/includes/admin/wp-site-health.php:261
132
+ msgid "MonsterInsights minor updates are enabled and you are getting the latest bugfixes and security updates, but not major features."
133
  msgstr ""
134
 
135
+ #: lite/includes/admin/wp-site-health.php:265
136
+ msgid "Automatic updates are disabled"
137
  msgstr ""
138
 
139
+ #: lite/includes/admin/wp-site-health.php:266
140
+ msgid "MonsterInsights automatic updates are disabled. We recommend enabling automatic updates so you can get access to the latest features, bugfixes, and security updates as they are released."
141
  msgstr ""
142
 
143
+ #: lite/includes/admin/wp-site-health.php:270
144
+ msgid "Update Settings"
 
 
 
 
145
  msgstr ""
146
 
147
+ #: lite/includes/admin/wp-site-health.php:285
148
+ msgid "eCommerce data is not being tracked"
 
 
 
 
149
  msgstr ""
150
 
151
+ #. Translators: The eCommerce store currently active.
152
+ #: lite/includes/admin/wp-site-health.php:292
153
+ msgid "You are using %s but the MonsterInsights eCommerce addon is not active, please Install & Activate it to start tracking eCommerce data."
 
 
 
154
  msgstr ""
155
 
156
+ #: lite/includes/admin/wp-site-health.php:297
157
+ #: lite/includes/admin/wp-site-health.php:323
158
+ #: lite/includes/admin/wp-site-health.php:350
159
+ msgid "View Addons"
160
  msgstr ""
161
 
162
+ #: lite/includes/admin/wp-site-health.php:312
163
+ msgid "AMP pages are not being tracked"
164
  msgstr ""
165
 
166
+ #: lite/includes/admin/wp-site-health.php:318
167
+ msgid "Your website has Google AMP-enabled pages set up but they are not tracked by Google Analytics at the moment. You need to Install & Activate the MonsterInsights AMP Addon."
168
  msgstr ""
169
 
170
+ #: lite/includes/admin/wp-site-health.php:339
171
+ msgid "Facebook Instant Articles pages are not being tracked"
172
  msgstr ""
173
 
174
+ #: lite/includes/admin/wp-site-health.php:345
175
+ msgid "Your website has Facebook Instant Articles pages set up but they are not tracked by Google Analytics at the moment. You need to Install & Activate the MonsterInsights Facebook Instant Articles Addon."
176
  msgstr ""
177
 
178
+ #: lite/includes/admin/wp-site-health.php:364
179
+ msgid "Can connect to MonsterInsights.com correctly"
180
  msgstr ""
181
 
182
+ #: lite/includes/admin/wp-site-health.php:370
183
+ msgid "The MonsterInsights API is reachable and no connection issues have been detected."
 
184
  msgstr ""
185
 
186
+ #: lite/includes/admin/wp-site-health.php:385
187
+ msgid "The MonsterInsights server is not reachable."
188
+ msgstr ""
189
+
190
+ #: lite/includes/admin/wp-site-health.php:386
191
+ msgid "Your server is blocking external requests to monsterinsights.com, please check your firewall settings or contact your host for more details."
192
+ msgstr ""
193
+
194
+ #. Translators: The error message received.
195
+ #: lite/includes/admin/wp-site-health.php:390
196
+ msgid "Error message: %s"
197
+ msgstr ""
198
+
199
+ #: lite/includes/admin/wp-site-health.php:403
200
+ msgid "Tracking code is properly being output."
201
+ msgstr ""
202
+
203
+ #: lite/includes/admin/wp-site-health.php:409
204
+ msgid "The Google Analytics tracking code is being output correctly, and no duplicate Google Analytics scripts have been detected."
205
+ msgstr ""
206
+
207
+ #: lite/includes/admin/wp-site-health.php:417
208
+ msgid "MonsterInsights has automatically detected an issue with your tracking setup"
209
+ msgstr ""
210
+
211
+ #: lite/includes/admin/tools.php:10
212
+ msgid "Want even more fine tuned control over your website analytics?"
213
+ msgstr ""
214
+
215
+ #: lite/includes/admin/tools.php:11
216
+ msgid "By upgrading to MonsterInsights Pro, you can unlock the MonsterInsights URL builder that helps you better track your advertising and email marketing campaigns."
217
+ msgstr ""
218
+
219
+ #: lite/includes/admin/tools.php:12
220
+ msgid "Click here to Upgrade"
221
+ msgstr ""
222
+
223
+ #: lite/includes/admin/connect.php:42
224
+ msgid "You are not allowed to install plugins."
225
+ msgstr ""
226
+
227
+ #: lite/includes/admin/connect.php:56
228
+ msgid "Please enter your license key to connect."
229
+ msgstr ""
230
+
231
+ #: lite/includes/admin/connect.php:67
232
+ msgid "Pro version is already installed."
233
+ msgstr ""
234
+
235
+ #: lite/includes/admin/connect.php:104
236
+ msgid "Could not install upgrade. Please download from monsterinsights.com and install manually."
237
+ msgstr ""
238
+
239
+ #: lite/includes/admin/connect.php:135
240
+ #: lite/includes/admin/connect.php:182
241
+ msgid "Plugin installed & activated."
242
+ msgstr ""
243
+
244
+ #: lite/includes/admin/connect.php:166
245
+ msgid "You are not licensed."
246
+ msgstr ""
247
+
248
+ #: lite/includes/admin/connect.php:186
249
+ msgid "Pro version installed but needs to be activated from the Plugins page inside your WordPress admin."
250
+ msgstr ""
251
+
252
+ #: lite/includes/admin/dashboard-widget.php:125
253
+ msgid "Analytics is not Setup"
254
+ msgstr ""
255
+
256
+ #: lite/includes/admin/dashboard-widget.php:126
257
+ msgid "Please connect MonsterInsights to Google Analytics to see reports."
258
+ msgstr ""
259
+
260
+ #: lite/includes/admin/dashboard-widget.php:127
261
+ msgid "Configure MonsterInsights"
262
+ msgstr ""
263
+
264
+ #: lite/includes/admin/onboarding-wizard.php:162
265
+ msgid "MonsterInsights &rsaquo; Onboarding Wizard"
266
+ msgstr ""
267
+
268
+ #: lite/includes/admin/onboarding-wizard.php:174
269
+ msgid "Return to Dashboard"
270
+ msgstr ""
271
+
272
+ #: lite/includes/admin/onboarding-wizard.php:240
273
+ msgid "You are not allowed to install plugins"
274
+ msgstr ""
275
+
276
+ #: lite/includes/admin/reports/report-queries.php:22
277
+ #: languages/vue.php:218
278
+ msgid "Search Console"
279
+ msgstr ""
280
+
281
+ #: lite/includes/admin/reports/report-ecommerce.php:22
282
+ #: languages/vue.php:215
283
+ msgid "eCommerce"
284
+ msgstr ""
285
+
286
+ #: lite/includes/admin/reports/report-realtime.php:22
287
+ msgid "Real Time"
288
+ msgstr ""
289
+
290
+ #: lite/includes/admin/reports/report-publisher.php:22
291
+ #: languages/vue.php:212
292
+ msgid "Publishers"
293
+ msgstr ""
294
+
295
+ #: lite/includes/admin/reports/report-dimensions.php:22
296
+ #: languages/vue.php:221
297
+ msgid "Dimensions"
298
+ msgstr ""
299
+
300
+ #: lite/includes/admin/reports/report-forms.php:22
301
+ #: languages/vue.php:224
302
+ msgid "Forms"
303
+ msgstr ""
304
+
305
+ #: lite/includes/admin/welcome.php:33
306
+ #: lite/includes/admin/welcome.php:34
307
+ #: languages/vue.php:1727
308
+ msgid "Welcome to MonsterInsights"
309
+ msgstr ""
310
+
311
+ #: includes/frontend/tracking/class-tracking-preview.php:77
312
+ msgid "You are currently in a preview window. MonsterInsights doesn't track preview window traffic to avoid false visit reports."
313
+ msgstr ""
314
+
315
+ #: includes/frontend/tracking/class-tracking-analytics.php:218
316
+ msgid "Note: MonsterInsights is not currently configured on this site. The site owner needs to authenticate with Google Analytics in the MonsterInsights settings panel."
317
+ msgstr ""
318
+
319
+ #: includes/frontend/tracking/class-tracking-analytics.php:221
320
+ msgid "Note: MonsterInsights does not track you as a logged in site administrator to prevent site owners from accidentally skewing their own Google Analytics data."
321
+ msgstr ""
322
+
323
+ #: includes/frontend/tracking/class-tracking-analytics.php:224
324
+ msgid "Note: The site owner has disabled Google Analytics tracking for your user role."
325
+ msgstr ""
326
+
327
+ #: includes/frontend/tracking/class-tracking-analytics.php:300
328
+ msgid "Not running function"
329
+ msgstr ""
330
+
331
+ #: includes/frontend/tracking/class-tracking-analytics.php:300
332
+ msgid "because you are not being tracked."
333
+ msgstr ""
334
+
335
+ #: includes/admin/review.php:110
336
+ msgid "Are you enjoying MonsterInsights?"
337
+ msgstr ""
338
+
339
+ #: includes/admin/review.php:112
340
+ msgid "Yes"
341
+ msgstr ""
342
+
343
+ #: includes/admin/review.php:113
344
+ msgid "Not Really"
345
+ msgstr ""
346
+
347
+ #: includes/admin/review.php:117
348
+ msgid "We're sorry to hear you aren't enjoying MonsterInsights. We would love a chance to improve. Could you take a minute and let us know what we can do better?"
349
+ msgstr ""
350
+
351
+ #: includes/admin/review.php:119
352
+ msgid "Give Feedback"
353
+ msgstr ""
354
+
355
+ #: includes/admin/review.php:120
356
+ msgid "No thanks"
357
+ msgstr ""
358
+
359
+ #: includes/admin/review.php:124
360
+ msgid "That’s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?"
361
+ msgstr ""
362
+
363
+ #: includes/admin/review.php:125
364
+ msgid "~ Syed Balkhi<br>Co-Founder of MonsterInsights"
365
+ msgstr ""
366
+
367
+ #: includes/admin/review.php:127
368
+ msgid "Ok, you deserve it"
369
+ msgstr ""
370
+
371
+ #: includes/admin/review.php:128
372
+ msgid "Nope, maybe later"
373
+ msgstr ""
374
+
375
+ #: includes/admin/review.php:129
376
+ msgid "I already did"
377
+ msgstr ""
378
+
379
+ #: includes/admin/tracking.php:242
380
+ msgid "Once Weekly"
381
+ msgstr ""
382
+
383
+ #: includes/admin/routes.php:272
384
+ msgid "The most beginner friendly drag & drop WordPress forms plugin allowing you to create beautiful contact forms, subscription forms, payment forms, and more in minutes, not hours!"
385
+ msgstr ""
386
+
387
+ #: includes/admin/routes.php:281
388
+ msgid "Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers."
389
+ msgstr ""
390
+
391
+ #: includes/admin/routes.php:291
392
+ msgid "SMTP (Simple Mail Transfer Protocol) is an industry standard for sending emails. SMTP helps increase email deliverability by using proper authentication"
393
+ msgstr ""
394
+
395
+ #: includes/admin/routes.php:409
396
+ msgid "Invalid UA code"
397
+ msgstr ""
398
+
399
+ #: includes/admin/routes.php:436
400
+ msgid "Please upload a valid .json file"
401
+ msgstr ""
402
+
403
+ #: includes/admin/routes.php:445
404
+ msgid "Please upload a file to import"
405
+ msgstr ""
406
+
407
+ #: includes/admin/routes.php:496
408
+ msgid "You don't have permission to view MonsterInsights reports."
409
+ msgstr ""
410
+
411
+ #: includes/admin/routes.php:508
412
+ msgid "You can't view MonsterInsights reports because you are not licensed."
413
+ msgstr ""
414
+
415
+ #: includes/admin/routes.php:509
416
+ msgid "Add your license"
417
+ msgstr ""
418
+
419
+ #: includes/admin/routes.php:516
420
+ msgid "You can't view MonsterInsights reports due to license key errors."
421
+ msgstr ""
422
+
423
+ #: includes/admin/routes.php:524
424
+ msgid "You must authenticate with MonsterInsights before you can view reports."
425
+ msgstr ""
426
+
427
+ #: includes/admin/routes.php:530
428
+ msgid "Unknown report. Try refreshing and retrying. Contact support if this issue persists."
429
+ msgstr ""
430
+
431
+ #: includes/admin/routes.php:576
432
+ msgid "We encountered an error when fetching the report data."
433
  msgstr ""
434
 
435
  #: includes/admin/api-auth.php:85
436
  msgid "You don't have permission to authenticate MonsterInsights."
437
  msgstr ""
438
 
439
+ #: includes/admin/api-auth.php:96
440
  msgid "Cannot authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings."
441
  msgstr ""
442
 
443
+ #: includes/admin/api-auth.php:102
444
  msgid "Cannot authenticate. Please re-authenticate."
445
  msgstr ""
446
 
447
+ #: includes/admin/api-auth.php:104
448
  msgid "Cannot network authenticate. Please re-authenticate on the network settings panel."
449
  msgstr ""
450
 
451
+ #: includes/admin/api-auth.php:240
452
  msgid "You don't have permission to re-authenticate MonsterInsights."
453
  msgstr ""
454
 
455
+ #: includes/admin/api-auth.php:251
456
+ msgid "Cannot re-authenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings."
457
+ msgstr ""
458
+
459
+ #: includes/admin/api-auth.php:257
460
+ msgid "Cannot re-authenticate. Please authenticate."
461
+ msgstr ""
462
+
463
+ #: includes/admin/api-auth.php:259
464
+ msgid "Cannot re-authenticate the network. Please authenticate on the network settings panel."
465
+ msgstr ""
466
+
467
+ #: includes/admin/api-auth.php:361
468
+ msgid "You don't have permission to verify MonsterInsights."
469
+ msgstr ""
470
+
471
+ #: includes/admin/api-auth.php:370
472
+ #: includes/admin/api-auth.php:372
473
+ msgid "Cannot verify. Please authenticate."
474
+ msgstr ""
475
+
476
+ #: includes/admin/api-auth.php:378
477
+ msgid "Cannot verify. Please enter a valid, active license key for MonsterInsights Pro into the settings."
478
+ msgstr ""
479
+
480
+ #: includes/admin/api-auth.php:384
481
+ msgid "Successfully verified."
482
+ msgstr ""
483
+
484
+ #: includes/admin/api-auth.php:386
485
+ msgid "Could not verify."
486
+ msgstr ""
487
+
488
+ #: includes/admin/api-auth.php:394
489
+ msgid "Verify auth key not passed"
490
+ msgstr ""
491
+
492
+ #: includes/admin/api-auth.php:416
493
+ msgid "You don't have permission to deauthenticate MonsterInsights."
494
+ msgstr ""
495
+
496
+ #: includes/admin/api-auth.php:425
497
+ #: includes/admin/api-auth.php:427
498
+ msgid "Cannot deauthenticate. You are not currently authed."
499
+ msgstr ""
500
+
501
+ #: includes/admin/api-auth.php:433
502
+ msgid "Cannot deauthenticate. Please enter a valid, active license key for MonsterInsights Pro into the settings."
503
+ msgstr ""
504
+
505
+ #: includes/admin/api-auth.php:441
506
+ msgid "Successfully deauthenticated."
507
+ msgstr ""
508
+
509
+ #: includes/admin/api-auth.php:444
510
+ msgid "Successfully force deauthenticated."
511
+ msgstr ""
512
+
513
+ #: includes/admin/api-auth.php:446
514
+ msgid "Could not deauthenticate."
515
+ msgstr ""
516
+
517
+ #: includes/admin/licensing/skin.php:86
518
+ msgid "There was an error installing the addon. Please try again."
519
+ msgstr ""
520
+
521
+ #: includes/admin/licensing/skin.php:94
522
+ msgid "There was an error installing the addon: %s"
523
+ msgstr ""
524
+
525
+ #: includes/admin/common.php:738
526
+ msgid "MonsterInsights has detected that it's files are being blocked. This is usually caused by a adblock browser plugin (particularly uBlock Origin), or a conflicting WordPress theme or plugin. This issue only affects the admin side of MonsterInsights. To solve this, ensure MonsterInsights is whitelisted for your website URL in any adblock browser plugin you use. For step by step directions on how to do this, %1$sclick here%2$s. If this doesn't solve the issue (rare), send us a ticket %3$shere%2$s and we'll be happy to help diagnose the issue."
527
+ msgstr ""
528
+
529
+ #: includes/admin/admin.php:38
530
+ #: includes/admin/admin.php:44
531
+ #: includes/admin/admin.php:54
532
+ #: includes/admin/admin.php:91
533
+ #: languages/vue.php:168
534
+ msgid "Insights"
535
+ msgstr ""
536
+
537
+ #: includes/admin/admin.php:41
538
+ #: includes/admin/admin.php:51
539
+ #: includes/admin/admin.php:177
540
+ msgid "Settings"
541
+ msgstr ""
542
+
543
+ #: includes/admin/admin.php:44
544
+ msgid "General:"
545
+ msgstr ""
546
+
547
+ #: includes/admin/admin.php:48
548
+ #: includes/admin/admin.php:54
549
+ #: includes/admin/admin.php:95
550
+ msgid "General Reports:"
551
+ msgstr ""
552
+
553
+ #: includes/admin/admin.php:48
554
+ #: includes/admin/admin.php:95
555
+ #: languages/vue.php:603
556
+ msgid "Reports"
557
+ msgstr ""
558
+
559
+ #: includes/admin/admin.php:60
560
+ msgid "Tools:"
561
  msgstr ""
562
 
563
+ #: includes/admin/admin.php:60
564
+ msgid "Tools"
565
  msgstr ""
566
 
567
+ #: includes/admin/admin.php:65
568
+ #: includes/admin/admin.php:98
569
+ msgid "Addons:"
570
  msgstr ""
571
 
572
+ #: includes/admin/admin.php:65
573
+ #: includes/admin/admin.php:98
574
+ msgid "Addons"
575
  msgstr ""
576
 
577
+ #: includes/admin/admin.php:69
578
+ msgid "About Us:"
 
579
  msgstr ""
580
 
581
+ #: includes/admin/admin.php:69
582
+ #: languages/vue.php:233
583
+ msgid "About Us"
584
  msgstr ""
585
 
586
+ #: includes/admin/admin.php:91
587
+ #: includes/admin/admin.php:93
588
+ msgid "Network Settings:"
589
  msgstr ""
590
 
591
+ #: includes/admin/admin.php:93
592
+ msgid "Network Settings"
593
  msgstr ""
594
 
595
+ #: includes/admin/admin.php:159
596
+ msgid "MonsterInsights Knowledge Base"
597
  msgstr ""
598
 
599
+ #: includes/admin/admin.php:159
600
+ msgid "Documentation"
601
  msgstr ""
602
 
603
+ #: includes/admin/admin.php:164
604
+ #: includes/admin/reports/abstract-report.php:360
605
+ msgid "Get MonsterInsights Pro"
606
  msgstr ""
607
 
608
+ #: includes/admin/admin.php:170
609
+ #: includes/admin/admin.php:173
610
+ #: languages/vue.php:939
611
+ msgid "Support"
612
  msgstr ""
613
 
614
+ #: includes/admin/admin.php:236
615
+ msgid "Please rate %sMonsterInsights%s %s on %sWordPress.org%s to help us spread the word. Thank you from the MonsterInsights team!"
616
  msgstr ""
617
 
618
+ #: includes/admin/admin.php:270
619
+ msgid "Please configure your %1$sGoogle Analytics settings%2$s!"
620
  msgstr ""
621
 
622
+ #: includes/admin/admin.php:279
623
+ msgid "Warning: No valid license key has been entered for MonsterInsights. You are currently not getting updates, and are not able to view reports. %1$sPlease click here to enter your license key and begin receiving updates and reports.%2$s"
624
  msgstr ""
625
 
626
+ #: includes/admin/admin.php:289
627
+ msgid "Your license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s"
628
  msgstr ""
629
 
630
+ #: includes/admin/admin.php:291
631
+ #: languages/vue.php:1238
632
+ msgid "Your license key for MonsterInsights has been disabled. Please use a different key."
633
  msgstr ""
634
 
635
+ #: includes/admin/admin.php:293
636
+ #: languages/vue.php:1241
637
+ msgid "Your license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key."
638
  msgstr ""
639
 
640
+ #: includes/admin/admin.php:297
641
+ msgid "Your network license key for MonsterInsights has expired. %1$sPlease click here to renew your license key.%2$s"
 
 
 
 
642
  msgstr ""
643
 
644
+ #: includes/admin/admin.php:299
645
+ msgid "Your network license key for MonsterInsights has been disabled. Please use a different key."
 
646
  msgstr ""
647
 
648
+ #: includes/admin/admin.php:301
649
+ msgid "Your network license key for MonsterInsights is invalid. The key no longer exists or the user associated with the key has been deleted. Please use a different key."
650
  msgstr ""
651
 
652
+ #: includes/admin/admin.php:317
653
+ msgid "Your site is running an outdated, insecure version of PHP (%1$s), which could be putting your site at risk for being hacked.%4$sWordPress will stop supporting your PHP version in April, 2019.%4$sUpdating PHP only takes a few minutes and will make your website significantly faster and more secure.%4$s%2$sLearn more about updating PHP%3$s"
654
  msgstr ""
655
 
656
+ #: includes/admin/admin.php:324
657
+ msgid "Your site is running an outdated version of WordPress (%1$s).%4$sMonsterInsights will stop supporting WordPress versions lower than 4.6 in April, 2019.%4$sUpdating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install.%4$s%2$sLearn more about updating WordPress%3$s"
658
  msgstr ""
659
 
660
+ #: includes/admin/admin.php:381
661
+ msgid "Important: You are currently using manual UA code output. We highly recommend %1$sauthenticating with MonsterInsights%2$s so that you can access our new reporting area and take advantage of new MonsterInsights features."
 
662
  msgstr ""
663
 
664
+ #: includes/admin/admin.php:423
665
+ #: includes/admin/admin.php:454
666
+ msgid "%1$sGet MonsterInsights Pro%2$s"
667
  msgstr ""
668
 
669
+ #: includes/admin/admin.php:467
670
+ msgid "Warning: MonsterInsights found cross-domain settings in the custom code field and converted them to the new settings structure. %1$sPlease click here to review and remove the code no longer needed.%2$s"
 
671
  msgstr ""
672
 
673
  #: includes/admin/notice.php:225
682
  msgid "There seems to be an issue running JavaScript on your website, which MonsterInsights is crafted in to give you the best experience possible."
683
  msgstr ""
684
 
685
+ #: includes/admin/pages/settings.php:91
686
+ msgid "If you are using an %sad blocker%s, please disable or whitelist the current page to load MonsterInsights correctly."
687
+ msgstr ""
688
+
689
+ #: includes/admin/pages/settings.php:103
690
  msgid "Copy the error message above and paste it in a message to the MonsterInsights support team."
691
  msgstr ""
692
 
693
+ #: includes/admin/pages/settings.php:106
694
  msgid "Resolve This Issue"
695
  msgstr ""
696
 
697
+ #: includes/admin/pages/settings.php:110
698
  msgid "Your browser version is not supported"
699
  msgstr ""
700
 
701
+ #: includes/admin/pages/settings.php:111
702
  msgid "You are using a browser which is no longer supported by MonsterInsights. Please update or use another browser in order to access the plugin settings."
703
  msgstr ""
704
 
705
+ #: includes/admin/pages/settings.php:113
706
  msgid "View supported browsers"
707
  msgstr ""
708
 
709
+ #: includes/admin/reports/overview.php:34
710
+ #: languages/vue.php:209
711
+ msgid "Overview"
712
+ msgstr ""
713
+
714
  #: includes/admin/reports/abstract-report.php:54
715
  msgid "Access denied"
716
  msgstr ""
735
  msgid "The Google oAuth authentication needs to be re-authenticated to view data."
736
  msgstr ""
737
 
738
+ #: includes/admin/reports/abstract-report.php:122
739
  msgid "No data found"
740
  msgstr ""
741
 
742
+ #: includes/admin/reports/abstract-report.php:168
743
  msgid "Invalid date range."
744
  msgstr ""
745
 
746
+ #: includes/admin/reports/abstract-report.php:269
747
  msgid "You must authenticate with MonsterInsights to use reports."
748
  msgstr ""
749
 
750
+ #: includes/admin/reports/abstract-report.php:318
751
  msgid "You currently have a %s level license, but this report requires at least a %s level license to view the %s. Please upgrade to view this report."
752
  msgstr ""
753
 
754
+ #: includes/admin/reports/abstract-report.php:330
755
  msgid "Ready to Get Analytics Super-Powers?"
756
  msgstr ""
757
 
758
+ #: includes/admin/reports/abstract-report.php:332
759
  msgid "(And Crush Your Competition?)"
760
  msgstr ""
761
 
762
+ #: includes/admin/reports/abstract-report.php:335
763
  msgid ""
764
+ "Hey there! It looks like you've got the %s license installed on your site.\n"
765
  "\t\t\t\t\t\t\t\t\t That's awesome! %s"
766
  msgstr ""
767
 
768
+ #: includes/admin/reports/abstract-report.php:338
769
  msgid "Do you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with the %s level%s of our paid packages. You'll need to upgrade your license to get instant access."
770
  msgstr ""
771
 
772
+ #: includes/admin/reports/abstract-report.php:340
773
  msgid "It's easy! To upgrade, navigate to %sMy Account%s on MonsterInsights.com, go to the licenses tab, and click upgrade. We also have a %sstep by step guide%s with pictures of this process."
774
  msgstr ""
775
 
776
+ #: includes/admin/reports/abstract-report.php:342
777
+ #: includes/admin/reports/abstract-report.php:351
778
  msgid "If you have any questions, don't hesitate to reach out. We're here to help."
779
  msgstr ""
780
 
781
+ #: includes/admin/reports/abstract-report.php:344
782
  msgid ""
783
+ "Hey there! %s It looks like you've got the free version of MonsterInsights installed on your site.\n"
784
  "\t\t\t\t\t\t\t\t\t That's awesome!"
785
  msgstr ""
786
 
787
+ #: includes/admin/reports/abstract-report.php:347
788
  msgid "Do you you want to access to %s reporting right now%s in your WordPress Dashboard? That comes with %s level%s of our paid packages. To get instant access, you'll want to buy a MonsterInsights license, which also gives you access to powerful addons, expanded reporting (including the ability to use custom date ranges), comprehensive tracking features (like UserID tracking) and access to our world-class support team."
789
  msgstr ""
790
 
791
+ #: includes/admin/reports/abstract-report.php:349
792
  msgid "Upgrading is easy! To upgrade, navigate to %sour pricing page%s, purchase the required license, and then follow the %sinstructions in the email receipt%s to upgrade. It only takes a few minutes to unlock the most powerful, yet easy to use analytics tracking system for WordPress."
793
  msgstr ""
794
 
795
+ #: includes/admin/reports/abstract-report.php:357
796
+ #: languages/vue.php:1320
797
  msgid "Upgrade Now"
798
  msgstr ""
799
 
800
+ #: includes/admin/reports/abstract-report.php:393
801
  msgid "Visit addons page"
802
  msgstr ""
803
 
804
+ #: includes/admin/reports/abstract-report.php:395
805
  msgid "Please ask your webmaster to enable this addon."
806
  msgstr ""
807
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
808
  #: includes/api-request.php:191
809
  msgid "The firewall of your server is blocking outbound calls. Please contact your hosting provider to fix this issue. %s"
810
  msgstr ""
847
  msgid "Reason: The API was unreachable because no external hosts are allowed on this site."
848
  msgstr ""
849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
850
  #: includes/helpers.php:366
851
  msgid "United States"
852
  msgstr ""
1855
  msgid "Zimbabwe"
1856
  msgstr ""
1857
 
1858
+ #. Translators: The placeholders are for making the "We noticed you're using a caching plugin" text bold.
1859
+ #: includes/helpers.php:1204
1860
+ msgid "%1$sWe noticed you're using a caching plugin or caching from your hosting provider.%2$s Be sure to clear the cache to ensure the tracking appears on all pages and posts. %3$s(See this guide on how to clear cache)%4$s."
1861
+ msgstr ""
1862
+
1863
+ #. Translators: The placeholders are for making the "We have detected multiple tracking codes" text bold & adding a link to support.
1864
+ #: includes/helpers.php:1206
1865
+ msgid "%1$sWe have detected multiple tracking codes%2$s! You should remove non-MonsterInsights ones. If you need help finding them please %3$sread this article%4$s."
1866
+ msgstr ""
1867
+
1868
+ #: includes/deprecated.php:126
1869
+ msgid "%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s!"
1870
+ msgstr ""
1871
+
1872
+ #: includes/deprecated.php:179
1873
+ msgid "%1$s is %3$sdeprecated%4$s since MonsterInsights version %2$s."
1874
+ msgstr ""
1875
+
1876
  #: languages/vue.php:5
1877
  msgid "Refreshing Report"
1878
  msgstr ""
2069
  msgid "Get Fresh Reports Data Every 60 Seconds"
2070
  msgstr ""
2071
 
2072
+ #: languages/vue.php:153
2073
  msgid "Overview Report"
2074
  msgstr ""
2075
 
2076
+ #: languages/vue.php:156
2077
  msgid "Loading Settings"
2078
  msgstr ""
2079
 
2080
+ #: languages/vue.php:159
2081
  msgid "Saving Changes..."
2082
  msgstr ""
2083
 
2084
+ #: languages/vue.php:162
2085
  msgid "Settings Updated"
2086
  msgstr ""
2087
 
2088
+ #: languages/vue.php:165
2089
  msgid "Could Not Save Changes"
2090
  msgstr ""
2091
 
2092
+ #: languages/vue.php:171
2093
  msgid "Congratulations! "
2094
  msgstr ""
2095
 
2096
+ #: languages/vue.php:174
2097
  msgid "You Successfully Unlocked the most powerful Analytics plugin"
2098
  msgstr ""
2099
 
2100
+ #: languages/vue.php:177
2101
  msgid "Publishers Report"
2102
  msgstr ""
2103
 
2104
+ #: languages/vue.php:180
2105
  msgid "eCommerce Report"
2106
  msgstr ""
2107
 
2108
+ #: languages/vue.php:183
2109
  msgid "Search Console Report"
2110
  msgstr ""
2111
 
2112
+ #: languages/vue.php:186
2113
  msgid "Dimensions Report"
2114
  msgstr ""
2115
 
2116
+ #: languages/vue.php:189
2117
  msgid "Forms Report"
2118
  msgstr ""
2119
 
2120
+ #: languages/vue.php:193
2121
  msgid "Real-Time Report"
2122
  msgstr ""
2123
 
2124
+ #: languages/vue.php:196
2125
  msgid "Recommended Plugin: %s"
2126
  msgstr ""
2127
 
2128
+ #: languages/vue.php:199
2129
  msgid "Install"
2130
  msgstr ""
2131
 
2137
  msgid "Learn More"
2138
  msgstr ""
2139
 
2140
+ #: languages/vue.php:227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2141
  msgid "Real-Time"
2142
  msgstr ""
2143
 
2144
+ #: languages/vue.php:230
2145
  msgid "Loading settings"
2146
  msgstr ""
2147
 
2148
+ #: languages/vue.php:236
2149
  msgid "Getting Started"
2150
  msgstr ""
2151
 
2153
  msgid "Lite vs Pro"
2154
  msgstr ""
2155
 
2156
+ #: languages/vue.php:243
2157
  msgid "General"
2158
  msgstr ""
2159
 
2160
+ #: languages/vue.php:246
2161
  msgid "Engagement"
2162
  msgstr ""
2163
 
2164
+ #: languages/vue.php:249
2165
  msgid "Publisher"
2166
  msgstr ""
2167
 
2168
+ #: languages/vue.php:252
2169
  msgid "Conversions"
2170
  msgstr ""
2171
 
2172
+ #: languages/vue.php:255
2173
  msgid "Advanced"
2174
  msgstr ""
2175
 
2176
+ #: languages/vue.php:258
2177
  msgid "URL Builder"
2178
  msgstr ""
2179
 
2180
+ #: languages/vue.php:261
2181
  msgid "Import Export"
2182
  msgstr ""
2183
 
2184
+ #: languages/vue.php:264
2185
  msgid "Time to Purchase"
2186
  msgstr ""
2187
 
2188
+ #: languages/vue.php:267
2189
  msgid "This list shows how many days from first visit it took users to purchase products from your site."
2190
  msgstr ""
2191
 
2192
+ #: languages/vue.php:270
2193
  msgid "Sessions to Purchase"
2194
  msgstr ""
2195
 
2196
+ #: languages/vue.php:273
2197
  msgid "This list shows the number of sessions it took users before they purchased a product from your website."
2198
  msgstr ""
2199
 
2200
+ #: languages/vue.php:276
2201
  msgid "Top Posts/Pages"
2202
  msgstr ""
2203
 
2204
+ #: languages/vue.php:279
2205
  msgid "This list shows the most viewed posts and pages on your website."
2206
  msgstr ""
2207
 
2208
+ #: languages/vue.php:282
2209
  msgid "New vs. Returning Visitors"
2210
  msgstr ""
2211
 
2212
+ #: languages/vue.php:285
2213
  msgid "This graph shows what percent of your user sessions come from new versus repeat visitors."
2214
  msgstr ""
2215
 
2216
+ #: languages/vue.php:288
2217
  msgid "Device Breakdown"
2218
  msgstr ""
2219
 
2220
+ #: languages/vue.php:291
2221
  msgid "This graph shows what percent of your visitor sessions are done using a traditional computer or laptop, tablet or mobile device to view your site."
2222
  msgstr ""
2223
 
2224
+ #: languages/vue.php:294
2225
  msgid "Top Landing Pages"
2226
  msgstr ""
2227
 
2228
+ #: languages/vue.php:297
2229
  msgid "This list shows the top pages users first land on when visiting your website."
2230
  msgstr ""
2231
 
2232
+ #: languages/vue.php:300
2233
  msgid "Top Exit Pages"
2234
  msgstr ""
2235
 
2236
+ #: languages/vue.php:303
2237
  msgid "This list shows the top pages users exit your website from."
2238
  msgstr ""
2239
 
2240
+ #: languages/vue.php:306
2241
  msgid "Top Outbound Links"
2242
  msgstr ""
2243
 
2244
+ #: languages/vue.php:309
2245
  msgid "This list shows the top links clicked on your website that go to another website."
2246
  msgstr ""
2247
 
2248
+ #: languages/vue.php:312
2249
  msgid "Top Affiliate Links"
2250
  msgstr ""
2251
 
2252
+ #: languages/vue.php:315
2253
  msgid "This list shows the top affiliate links your visitors clicked on."
2254
  msgstr ""
2255
 
2256
+ #: languages/vue.php:318
2257
  msgid "Top Download Links"
2258
  msgstr ""
2259
 
2260
+ #: languages/vue.php:321
2261
  msgid "This list shows the download links your visitors clicked the most."
2262
  msgstr ""
2263
 
2264
+ #: languages/vue.php:324
2265
  msgid "Top Products"
2266
  msgstr ""
2267
 
2268
+ #: languages/vue.php:327
2269
  msgid "This list shows the top selling products on your website."
2270
  msgstr ""
2271
 
2272
+ #: languages/vue.php:330
2273
  msgid "Top Conversion Sources"
2274
  msgstr ""
2275
 
2276
+ #: languages/vue.php:333
2277
  msgid "This list shows the top referral websites in terms of product revenue."
2278
  msgstr ""
2279
 
2280
+ #: languages/vue.php:336
2281
  msgid "Total Add/Remove"
2282
  msgstr ""
2283
 
2284
+ #: languages/vue.php:339
2285
  msgid "Exit Setup"
2286
  msgstr ""
2287
 
2288
+ #: languages/vue.php:342
2289
  msgid "Yikes! PHP Update Required"
2290
  msgstr ""
2291
 
2292
+ #: languages/vue.php:345
2293
  msgid "MonsterInsights has detected that your site is running an outdated, insecure version of PHP (%s), which could be putting your site at risk for being hacked. WordPress itself will stop supporting your PHP version in April, 2019. Updating to the recommended version (PHP %s) only takes a few minutes and will make your website significantly faster and more secure."
2294
  msgstr ""
2295
 
2296
+ #: languages/vue.php:348
2297
  msgid "Learn more about updating PHP"
2298
  msgstr ""
2299
 
2300
+ #: languages/vue.php:351
2301
  msgid "Yikes! WordPress Update Required"
2302
  msgstr ""
2303
 
2304
+ #: languages/vue.php:354
2305
  msgid "MonsterInsights has detected that your site is running an outdated version of WordPress (%s). MonsterInsights will stop supporting WordPress versions lower than 4.6 in April, 2019. Updating WordPress takes just a few minutes and will also solve many bugs that exist in your WordPress install."
2306
  msgstr ""
2307
 
2308
+ #: languages/vue.php:357
2309
  msgid "Learn more about updating WordPress"
2310
  msgstr ""
2311
 
2312
+ #: languages/vue.php:360
2313
  msgid "Powered by MonsterInsights"
2314
  msgstr ""
2315
 
2316
+ #: languages/vue.php:363
2317
  msgid "Save Changes"
2318
  msgstr ""
2319
 
2320
+ #: languages/vue.php:366
2321
  msgid "New"
2322
  msgstr ""
2323
 
2324
+ #: languages/vue.php:369
2325
  msgid "Returning"
2326
  msgstr ""
2327
 
2328
+ #: languages/vue.php:372
2329
  msgid "Desktop"
2330
  msgstr ""
2331
 
2332
+ #: languages/vue.php:375
2333
  msgid "Tablet"
2334
  msgstr ""
2335
 
2336
+ #: languages/vue.php:378
2337
  msgid "Mobile"
2338
  msgstr ""
2339
 
2340
+ #: languages/vue.php:381
2341
  msgid "Sessions"
2342
  msgstr ""
2343
 
2344
+ #: languages/vue.php:384
2345
  msgid "Unique %s Sessions"
2346
  msgstr ""
2347
 
2348
+ #: languages/vue.php:387
2349
  msgid "Pageviews"
2350
  msgstr ""
2351
 
2352
+ #: languages/vue.php:390
2353
  msgid "Unique %s Pageviews"
2354
  msgstr ""
2355
 
2356
+ #: languages/vue.php:393
2357
  msgid "Avg. Session Duration"
2358
  msgstr ""
2359
 
2360
+ #: languages/vue.php:396
2361
  msgid "Bounce Rate"
2362
  msgstr ""
2363
 
2364
+ #: languages/vue.php:399
2365
  msgid "Top 10 Countries"
2366
  msgstr ""
2367
 
2368
+ #: languages/vue.php:402
2369
  msgid "View Countries Report"
2370
  msgstr ""
2371
 
2372
+ #: languages/vue.php:405
2373
  msgid "Top 10 Referrals"
2374
  msgstr ""
2375
 
2376
+ #: languages/vue.php:408
2377
  msgid "View All Referral Sources"
2378
  msgstr ""
2379
 
2380
+ #: languages/vue.php:411
2381
  msgid "View Full Posts/Pages Report"
2382
  msgstr ""
2383
 
2384
+ #: languages/vue.php:414
2385
  msgid "A session is the browsing session of a single user to your site."
2386
  msgstr ""
2387
 
2388
+ #: languages/vue.php:417
2389
  msgid "A pageview is defined as a view of a page on your site that is being tracked by the Analytics tracking code. Each refresh of a page is also a new pageview."
2390
  msgstr ""
2391
 
2392
+ #: languages/vue.php:420
2393
  msgid "Total duration of all sessions (in seconds) / number of sessions."
2394
  msgstr ""
2395
 
2396
+ #: languages/vue.php:423
2397
  msgid "Percentage of single-page visits (or web sessions). It is the number of visits in which a person leaves your website from the landing page without browsing any further."
2398
  msgstr ""
2399
 
2400
+ #: languages/vue.php:426
2401
  msgid "This list shows the top countries your website visitors are from."
2402
  msgstr ""
2403
 
2404
+ #: languages/vue.php:429
2405
  msgid "This list shows the top websites that send your website traffic, known as referral traffic."
2406
  msgstr ""
2407
 
2408
+ #: languages/vue.php:432
2409
  msgid "MonsterInsights Addons"
2410
  msgstr ""
2411
 
2412
+ #: languages/vue.php:435
2413
  msgid "Search Addons"
2414
  msgstr ""
2415
 
2416
+ #: languages/vue.php:438
2417
  msgid "Yes (recommended) %s- Get the latest features, bugfixes, and security updates as they are released.%s"
2418
  msgstr ""
2419
 
2420
+ #: languages/vue.php:441
2421
  msgid "Minor only %s- Get bugfixes and security updates, but not major features.%s"
2422
  msgstr ""
2423
 
2424
+ #: languages/vue.php:444
2425
  msgid "None %s- Manually update everything.%s"
2426
  msgstr ""
2427
 
2428
+ #: languages/vue.php:447
2429
  msgid "License Key"
2430
  msgstr ""
2431
 
2432
+ #: languages/vue.php:450
2433
  msgid "Google Authentication"
2434
  msgstr ""
2435
 
2436
+ #: languages/vue.php:453
2437
  msgid "Connect Google Analytics + WordPress"
2438
  msgstr ""
2439
 
2440
+ #: languages/vue.php:456
2441
  msgid "You will be taken to the MonsterInsights website where you'll need to connect your Analytics account."
2442
  msgstr ""
2443
 
2444
+ #: languages/vue.php:459
2445
  msgid "Automatic Updates"
2446
  msgstr ""
2447
 
2448
+ #: languages/vue.php:462
2449
  msgid "Setup Wizard"
2450
  msgstr ""
2451
 
2452
+ #: languages/vue.php:465
2453
  msgid "Use our configuration wizard to properly setup Google Analytics with WordPress (with just a few clicks)."
2454
  msgstr ""
2455
 
2456
+ #: languages/vue.php:468
2457
  msgid "Launch Setup Wizard"
2458
  msgstr ""
2459
 
2460
+ #: languages/vue.php:471
2461
  msgid "Path (example: %s)"
2462
  msgstr ""
2463
 
2464
+ #: languages/vue.php:474
2465
  msgid "Path has to start with a / and have no spaces"
2466
  msgstr ""
2467
 
2468
+ #: languages/vue.php:477
2469
  msgid "Label (example: %s)"
2470
  msgstr ""
2471
 
2472
+ #: languages/vue.php:480
2473
  msgid "Label can't contain any spaces"
2474
  msgstr ""
2475
 
2476
+ #: languages/vue.php:483
2477
  msgid "Affiliate Links"
2478
  msgstr ""
2479
 
2480
+ #: languages/vue.php:486
2481
  msgid "This allows you to track custom affiliate links. A path of /go/ would match urls that start with that. The label is appended onto the end of the string \"outbound-link-\", to provide unique labels for these links in Google Analytics. Complete documentation on affiliate links is available %shere%s."
2482
  msgstr ""
2483
 
2484
+ #: languages/vue.php:489
2485
  msgid "Our affiliate link tracking works by setting path for internal links to track as outbound links."
2486
  msgstr ""
2487
 
2488
+ #: languages/vue.php:492
2489
  msgid "Demographics"
2490
  msgstr ""
2491
 
2492
+ #: languages/vue.php:495
2493
  msgid "Enable Demographics and Interests Reports for Remarketing and Advertising"
2494
  msgstr ""
2495
 
2496
+ #: languages/vue.php:498
2497
  msgid "Anonymize IP Addresses"
2498
  msgstr ""
2499
 
2500
+ #: languages/vue.php:501
2501
  msgid "Link Attribution"
2502
  msgstr ""
2503
 
2504
+ #: languages/vue.php:504
2505
  msgid "Enable Enhanced Link Attribution"
2506
  msgstr ""
2507
 
2508
+ #: languages/vue.php:507
2509
  msgid "Enable Anchor Tracking"
2510
  msgstr ""
2511
 
2512
+ #: languages/vue.php:510
2513
  msgid "Enable allowAnchor"
2514
  msgstr ""
2515
 
2516
+ #: languages/vue.php:513
2517
  msgid "Enable allowLinker"
2518
  msgstr ""
2519
 
2520
+ #: languages/vue.php:516
2521
  msgid "Enable Tag Links in RSS"
2522
  msgstr ""
2523
 
2524
+ #: languages/vue.php:519
2525
  msgid "File Downloads"
2526
  msgstr ""
2527
 
2528
+ #: languages/vue.php:522
2529
  msgid "Extensions of Files to Track as Downloads"
2530
  msgstr ""
2531
 
2532
+ #: languages/vue.php:525
2533
  msgid "MonsterInsights will send an event to Google Analytics if a link to a file has one of the above extensions."
2534
  msgstr ""
2535
 
2536
+ #: languages/vue.php:528
2537
  msgid "Enable this setting to add the Demographics and Remarketing features to your Google Analytics tracking code. Make sure to enable Demographics and Remarketing in your Google Analytics account. We have a guide for how to do that in our %sknowledge base%s. For more information about Remarketing, we refer you to %sGoogle's documentation%s. Note that usage of this function is affected by privacy and cookie laws around the world. Be sure to follow the laws that affect your target audience."
2538
  msgstr ""
2539
 
2540
+ #: languages/vue.php:531
2541
  msgid "This adds %sanonymizeIp%s, telling Google Analytics to anonymize the information sent by the tracker objects by removing the last octet of the IP address prior to its storage."
2542
  msgstr ""
2543
 
2544
+ #: languages/vue.php:534
2545
  msgid "Add %sEnhanced Link Attribution%s to your tracking code."
2546
  msgstr ""
2547
 
2548
+ #: languages/vue.php:537
2549
  msgid "Many WordPress \"1-page\" style themes rely on anchor tags for navigation to show virtual pages. The problem is that to Google Analytics, these are all just a single page, and it makes it hard to get meaningful statistics about pages viewed. This feature allows proper tracking in those themes."
2550
  msgstr ""
2551
 
2552
+ #: languages/vue.php:540
2553
  msgid "This adds %sallowAnchor%s to the create command of the pageview hit tracking code, and makes RSS link tagging use a # as well."
2554
  msgstr ""
2555
 
2556
+ #: languages/vue.php:543
2557
  msgid "Enabling %scross-domain tracking (additional setup required)%s allows you to track users across multiple properties you own (such as example-1.com and example-2.com as a single session. It also allows you fix an issue so that when a user has to go to an off-site hosted payment gateway to finish a purchase it doesn't count it as referral traffic from that gateway but maintains the visit as part of the same session.) It is required that the other site includes a Google Analytics tracker with the same UA Code."
2558
  msgstr ""
2559
 
2560
+ #: languages/vue.php:546
2561
  msgid "Do not use this feature if you use FeedBurner, as FeedBurner can do this automatically and better than this plugin can. Check this %shelp page%s for info on how to enable this feature in FeedBurner."
2562
  msgstr ""
2563
 
2564
+ #: languages/vue.php:549
2565
  msgid "Add domain"
2566
  msgstr ""
2567
 
2568
+ #: languages/vue.php:552
2569
  msgid "Domain (example: %s)"
2570
  msgstr ""
2571
 
2572
+ #: languages/vue.php:555
2573
  msgid "Please enter domain names only ( example: example.com not http://example.com ) and not current site domain ( %s )."
2574
  msgstr ""
2575
 
2576
+ #: languages/vue.php:558
2577
  msgid "Cross Domain Tracking"
2578
  msgstr ""
2579
 
2580
+ #: languages/vue.php:561
2581
  msgid "Cross domain tracking makes it possible for Analytics to see sessions on two related sites as a single session. More info on specific setup steps can be found in our %sknowledge base%s."
2582
  msgstr ""
2583
 
2584
+ #: languages/vue.php:564
2585
  msgid "It looks like you added a Google Analytics tracking code in the custom code area, this can potentially prevent proper tracking. If you want to use a manual UA please use the setting in the %sGeneral%s tab."
2586
  msgstr ""
2587
 
2588
+ #: languages/vue.php:567
2589
  msgid "Permissions"
2590
  msgstr ""
2591
 
2592
+ #: languages/vue.php:570
2593
  msgid "Allow These User Roles to See Reports"
2594
  msgstr ""
2595
 
2596
+ #: languages/vue.php:573
2597
  msgid "Users that have at least one of these roles will be able to view the reports."
2598
  msgstr ""
2599
 
2600
+ #: languages/vue.php:576
2601
  msgid "Users that have at least one of these roles will be able to view the reports, along with any user with the manage_options capability."
2602
  msgstr ""
2603
 
2604
+ #: languages/vue.php:579
2605
  msgid "Allow These User Roles to Save Settings"
2606
  msgstr ""
2607
 
2608
+ #: languages/vue.php:582
2609
  msgid "Users that have at least one of these roles will be able to view and save the settings panel."
2610
  msgstr ""
2611
 
2612
+ #: languages/vue.php:585
2613
  msgid "Users that have at least one of these roles will be able to view and save the settings panel, along with any user with the manage_options capability."
2614
  msgstr ""
2615
 
2616
+ #: languages/vue.php:588
2617
  msgid "Exclude These User Roles From Tracking"
2618
  msgstr ""
2619
 
2620
+ #: languages/vue.php:591
2621
  msgid "Users that have at least one of these roles will not be tracked into Google Analytics."
2622
  msgstr ""
2623
 
2624
+ #: languages/vue.php:594
2625
  msgid "Performance"
2626
  msgstr ""
2627
 
2628
+ #: languages/vue.php:597
2629
  msgid "Custom code"
2630
  msgstr ""
2631
 
2632
+ #: languages/vue.php:600
2633
  msgid "Not for the average user: this allows you to add a line of code, to be added before the %spageview is sent%s."
2634
  msgstr ""
2635
 
2636
+ #: languages/vue.php:606
2637
  msgid "You must have the \"unfiltered_html\" capability to view/edit this setting."
2638
  msgstr ""
2639
 
2640
+ #: languages/vue.php:609
2641
  msgid "Hide Admin Bar Reports"
2642
  msgstr ""
2643
 
2644
+ #: languages/vue.php:612
2645
  msgid "Enabled %s- Show reports and dashboard widget.%s"
2646
  msgstr ""
2647
 
2648
+ #: languages/vue.php:615
2649
  msgid "Dashboard Widget Only %s- Disable reports, but show dashboard widget.%s"
2650
  msgstr ""
2651
 
2652
+ #: languages/vue.php:618
2653
  msgid "Disabled %s- Hide reports and dashboard widget.%s"
2654
  msgstr ""
2655
 
2656
+ #: languages/vue.php:621
2657
  msgid "Hello and welcome to MonsterInsights, the best Google Analytics plugin for WordPress. MonsterInsights shows you exactly which content gets the most visit, so you can analyze and optimize it for higher conversions."
2658
  msgstr ""
2659
 
2660
+ #: languages/vue.php:624
2661
  msgid "Over the years, we found that in order to get the most out of Google Analytics, you needed a full time developer who could implement custom tracking, so that Google Analytics would integrate with things like WooCommerce, and track things which Google doesn't by default, like outbound links."
2662
  msgstr ""
2663
 
2664
+ #: languages/vue.php:627
2665
  msgid "Our goal is to take the pain out of analytics, making it simple and easy, by eliminating the need to have to worry about code, putting the best reports directly into the area you already go to (your WordPress dashboard), and adding the most advanced insights and features without complicating our plugin with tons of settings. Quite simply, it should \"just work\"."
2666
  msgstr ""
2667
 
2668
+ #: languages/vue.php:630
2669
  msgid "MonsterInsights is brought to you by the same team that's behind the largest WordPress resource site, WPBeginner, the most popular lead-generation software, OptinMonster, and the best WordPress forms plugin, WPForms."
2670
  msgstr ""
2671
 
2672
+ #: languages/vue.php:633
2673
  msgid "Yup, we know a thing or two about building awesome products that customer love."
2674
  msgstr ""
2675
 
2676
+ #: languages/vue.php:636
2677
  msgid "The MonsterInsights Team: Syed, Chris, Jay, Mircea, Sunita and Basanta"
2678
  msgstr ""
2679
 
2680
+ #: languages/vue.php:639
2681
  msgid "Import/Export"
2682
  msgstr ""
2683
 
2684
+ #: languages/vue.php:642
2685
  msgid "Import"
2686
  msgstr ""
2687
 
2688
+ #: languages/vue.php:645
2689
  msgid "Import settings from another MonsterInsights website."
2690
  msgstr ""
2691
 
2692
+ #: languages/vue.php:648
2693
  msgid "Export"
2694
  msgstr ""
2695
 
2696
+ #: languages/vue.php:651
2697
  msgid "Export settings to import into another MonsterInsights install."
2698
  msgstr ""
2699
 
2700
+ #: languages/vue.php:654
2701
  msgid "Import Settings"
2702
  msgstr ""
2703
 
2704
+ #: languages/vue.php:657
2705
  msgid "Export Settings"
2706
  msgstr ""
2707
 
2708
+ #: languages/vue.php:660
2709
  msgid "Please choose a file to import"
2710
  msgstr ""
2711
 
2712
+ #: languages/vue.php:663
2713
  msgid "Use the filepicker below to select the settings export file from another site."
2714
  msgstr ""
2715
 
2716
+ #: languages/vue.php:666
2717
  msgid "Use the button below to export a file with your MonsterInsights settings."
2718
  msgstr ""
2719
 
2720
+ #: languages/vue.php:669
2721
  msgid "Uploading file..."
2722
  msgstr ""
2723
 
2724
+ #: languages/vue.php:672
2725
  msgid "File imported"
2726
  msgstr ""
2727
 
2728
+ #: languages/vue.php:675
2729
  msgid "Settings successfully updated!"
2730
  msgstr ""
2731
 
2732
+ #: languages/vue.php:678
2733
  msgid "Error importing settings"
2734
  msgstr ""
2735
 
2736
+ #: languages/vue.php:681
2737
  msgid "Please choose a .json file generated by a MonsterInsights settings export."
2738
  msgstr ""
2739
 
2740
+ #: languages/vue.php:684
2741
  msgid "Ok"
2742
  msgstr ""
2743
 
2744
+ #: languages/vue.php:687
2745
  msgid "Custom Campaign Parameters"
2746
  msgstr ""
2747
 
2748
+ #: languages/vue.php:690
2749
  msgid "The URL builder helps you add parameters to your URLs you use in custom web or email ad campaigns."
2750
  msgstr ""
2751
 
2752
+ #: languages/vue.php:693
2753
  msgid "A custom campaign is any ad campaign not using the AdWords auto-tagging feature. When users click one of the custom links, the unique parameters are sent to your Analytics account, so you can identify the urls that are the most effective in attracting users to your content."
2754
  msgstr ""
2755
 
2756
+ #: languages/vue.php:696
2757
  msgid "Website URL %s"
2758
  msgstr ""
2759
 
2760
+ #: languages/vue.php:699
2761
  msgid "The full website URL (e.g. %s %s%s)"
2762
  msgstr ""
2763
 
2764
+ #: languages/vue.php:702
2765
  msgid "Campaign Source %s"
2766
  msgstr ""
2767
 
2768
+ #: languages/vue.php:705
2769
  msgid "Enter a referrer (e.g. %sfacebook, newsletter, google%s)"
2770
  msgstr ""
2771
 
2772
+ #: languages/vue.php:708
2773
  msgid "Enter a marketing medium (e.g. %scpc, banner, email%s)"
2774
  msgstr ""
2775
 
2776
+ #: languages/vue.php:711
2777
  msgid "Enter a name to easily identify (e.g. %sspring_sale%s)"
2778
  msgstr ""
2779
 
2780
+ #: languages/vue.php:714
2781
  msgid "Enter the paid keyword"
2782
  msgstr ""
2783
 
2784
+ #: languages/vue.php:717
2785
  msgid "Enter something to differentiate ads"
2786
  msgstr ""
2787
 
2788
+ #: languages/vue.php:720
2789
  msgid "Use Fragment"
2790
  msgstr ""
2791
 
2792
+ #: languages/vue.php:723
2793
  msgid "Set the parameters in the fragment portion of the URL %s(not recommended)%s"
2794
  msgstr ""
2795
 
2796
+ #: languages/vue.php:726
2797
  msgid "URL to use"
2798
  msgstr ""
2799
 
2800
+ #: languages/vue.php:729
2801
  msgid "Updates automatically"
2802
  msgstr ""
2803
 
2804
+ #: languages/vue.php:732
2805
  msgid "Copy to clipboard"
2806
  msgstr ""
2807
 
2808
+ #: languages/vue.php:735
2809
  msgid "More Information & Examples"
2810
  msgstr ""
2811
 
2812
+ #: languages/vue.php:738
2813
  msgid "The following table gives a detailed explanation and example of each of the campaign parameters."
2814
  msgstr ""
2815
 
2816
+ #: languages/vue.php:741
2817
  msgid "Campaign Source"
2818
  msgstr ""
2819
 
2820
+ #: languages/vue.php:744
2821
  msgid "Required. Use utm_source to identify a search engine, newsletter name, or other source."
2822
  msgstr ""
2823
 
2824
+ #: languages/vue.php:747
2825
  msgid "Campaign Medium"
2826
  msgstr ""
2827
 
2828
+ #: languages/vue.php:750
2829
  msgid "Use utm_medium to identify a medium such as email or cost-per-click."
2830
  msgstr ""
2831
 
2832
+ #: languages/vue.php:753
2833
  msgid "Campaign Name"
2834
  msgstr ""
2835
 
2836
+ #: languages/vue.php:756
2837
  msgid "Used for keyword analysis. Use utm_campaign to identify a specific product promotion or strategic campaign."
2838
  msgstr ""
2839
 
2840
+ #: languages/vue.php:759
2841
  msgid "Campaign Term"
2842
  msgstr ""
2843
 
2844
+ #: languages/vue.php:762
2845
  msgid "Used for paid search. Use utm_term to note the keywords for this ad."
2846
  msgstr ""
2847
 
2848
+ #: languages/vue.php:765
2849
  msgid "Campaign Content"
2850
  msgstr ""
2851
 
2852
+ #: languages/vue.php:768
2853
  msgid "Used for A/B testing and content-targeted ads. Use utm_content to differentiate ads or links that point to the same URL."
2854
  msgstr ""
2855
 
2856
+ #: languages/vue.php:771
2857
  msgid "Example: %s"
2858
  msgstr ""
2859
 
2860
+ #: languages/vue.php:774
2861
  msgid "Examples: %s"
2862
  msgstr ""
2863
 
2864
+ #: languages/vue.php:777
2865
  msgid "About Campaigns"
2866
  msgstr ""
2867
 
2868
+ #: languages/vue.php:780
2869
  msgid "About Custom Campaigns"
2870
  msgstr ""
2871
 
2872
+ #: languages/vue.php:783
2873
  msgid "Best practices for creating Custom Campaigns"
2874
  msgstr ""
2875
 
2876
+ #: languages/vue.php:786
2877
  msgid "About the Referral Traffic report"
2878
  msgstr ""
2879
 
2880
+ #: languages/vue.php:789
2881
  msgid "About traffic source dimensions"
2882
  msgstr ""
2883
 
2884
+ #: languages/vue.php:792
2885
  msgid "AdWords Auto-Tagging"
2886
  msgstr ""
2887
 
2888
+ #: languages/vue.php:795
2889
  msgid "Additional Information"
2890
  msgstr ""
2891
 
2892
+ #: languages/vue.php:798
2893
  msgid "GDPR Guide"
2894
  msgstr ""
2895
 
2896
+ #: languages/vue.php:801
2897
  msgid "Compliance with European data laws including GDPR can be confusing and time-consuming. In order to help MonsterInsights users comply with these laws, we’ve created an addon that automates a lot of the necessary configuration changes for you. "
2898
  msgstr ""
2899
 
2900
+ #: languages/vue.php:804
2901
  msgid "How to install and activate MonsterInsights addons"
2902
  msgstr ""
2903
 
2904
+ #: languages/vue.php:807
2905
  msgid "The process for installing and activating addons is quick and easy after you install the MonsterInsights plugin. In this guide we’ll walk you through the process, step by step."
2906
  msgstr ""
2907
 
2908
+ #: languages/vue.php:810
2909
  msgid "Enabling eCommerce Tracking and Reports"
2910
  msgstr ""
2911
 
2912
+ #: languages/vue.php:813
2913
  msgid "Want to track your eCommerce sales data for your WooCommerce, MemberPress, or Easy Digital Downloads store with MonsterInsights? In this guide, we’ll show you how to enable eCommerce tracking in Google Analytics in just a few clicks."
2914
  msgstr ""
2915
 
2916
+ #: languages/vue.php:816
2917
  msgid "Read Documentation"
2918
  msgstr ""
2919
 
2920
+ #: languages/vue.php:819
2921
  msgid "Getting Started with MonsterInsights"
2922
  msgstr ""
2923
 
2924
+ #: languages/vue.php:822
2925
  msgid "MonsterInsights is the easiest analytics solution on the market to get started with, as we walk you through exactly what you need to do, in plain english, using our 3 minute setup wizard."
2926
  msgstr ""
2927
 
2928
+ #: languages/vue.php:825
2929
  msgid "To begin with, we’ll get your site authorized with Google Analytics, so we can start tracking and generating reports for you right away."
2930
  msgstr ""
2931
 
2932
+ #: languages/vue.php:828
2933
  msgid "In no time at all, and after just a few clicks, you'll have setup the most powerful Google Analytics tracking available for WordPress. It's easy to double your traffic and sales when you know exactly how people find and use your website. Let's get started!."
2934
  msgstr ""
2935
 
2936
+ #: languages/vue.php:831
2937
  msgid "Launch the wizard!"
2938
  msgstr ""
2939
 
2940
+ #: languages/vue.php:834
2941
  msgid "Get MonsterInsights Pro and Unlock all the Powerful Features"
2942
  msgstr ""
2943
 
2944
+ #: languages/vue.php:837
2945
  msgid "Thanks for being a loyal MonsterInsights Lite user. %sUpgrade to MonsterInsights Pro%s to unlock all the awesome features and experience why MonsterInsights is consistently rated the best Google Analytics solution for WordPress."
2946
  msgstr ""
2947
 
2948
+ #: languages/vue.php:840
2949
  msgid "Universal Tracking across devices and campaigns with just a few clicks."
2950
  msgstr ""
2951
 
2952
+ #: languages/vue.php:843
2953
  msgid "See your website analytics reports inside the WordPress dashboard"
2954
  msgstr ""
2955
 
2956
+ #: languages/vue.php:846
2957
  msgid "Get real-time stats right inside WordPress"
2958
  msgstr ""
2959
 
2960
+ #: languages/vue.php:849
2961
  msgid "1-click Google Analytics Enhanced Ecommerce tracking"
2962
  msgstr ""
2963
 
2964
+ #: languages/vue.php:852
2965
  msgid "Get detailed stats for each post and page."
2966
  msgstr ""
2967
 
2968
+ #: languages/vue.php:855
2969
  msgid "Automatically track clicks on your affiliate links and ads."
2970
  msgstr ""
2971
 
2972
+ #: languages/vue.php:858
2973
  msgid "Make Google Analytics GDPR compliant automatically"
2974
  msgstr ""
2975
 
2976
+ #: languages/vue.php:861
2977
  msgid "Setup tracking for authors, categories, tags, custom post types, users and more"
2978
  msgstr ""
2979
 
2980
+ #: languages/vue.php:864
2981
  msgid "Enable Google Optimize for A/B testing, adjust sample speed & sample rate."
2982
  msgstr ""
2983
 
2984
+ #: languages/vue.php:867
2985
  msgid "More advanced features"
2986
  msgstr ""
2987
 
2988
+ #: languages/vue.php:870
2989
  msgid "Get MonsterInsights Pro Today and Unlock all the Powerful Features"
2990
  msgstr ""
2991
 
2992
+ #: languages/vue.php:873
2993
  msgid "Bonus: MonsterInsights Lite users get %s50%% off regular price%s, automatically applied at checkout."
2994
  msgstr ""
2995
 
2996
+ #: languages/vue.php:876
2997
  msgid "How to Connect to Google Analytics"
2998
  msgstr ""
2999
 
3000
+ #: languages/vue.php:879
3001
  msgid "After you install MonsterInsights, you’ll need to connect your WordPress site with your Google Analytics account. MonsterInsights makes the process easy, with no coding required."
3002
  msgstr ""
3003
 
3004
+ #: languages/vue.php:882
3005
  msgid "Guide and Checklist for Advanced Insights"
3006
  msgstr ""
3007
 
3008
+ #: languages/vue.php:885
3009
  msgid "Our goal is to make it as easy as possible for you to measure and track your stats so you can grow your business. This easy-to-follow guide and checklist will get you set up with MonsterInsights’ advanced tracking."
3010
  msgstr ""
3011
 
3012
+ #: languages/vue.php:888
3013
  msgid "WordPress Admin Area Reports"
3014
  msgstr ""
3015
 
3016
+ #: languages/vue.php:891
3017
  msgid "Standard Reports"
3018
  msgstr ""
3019
 
3020
+ #: languages/vue.php:894
3021
  msgid "Overview Reports for the last 30 days."
3022
  msgstr ""
3023
 
3024
+ #: languages/vue.php:897
3025
  msgid "Advanced Reports"
3026
  msgstr ""
3027
 
3028
+ #: languages/vue.php:900
3029
  msgid "Publisher, eCommerce, Search Console, Custom Dimensions, Forms and Real-Time with custom date period selection"
3030
  msgstr ""
3031
 
3032
+ #: languages/vue.php:903
3033
  msgid "Dashboard Widget"
3034
  msgstr ""
3035
 
3036
+ #: languages/vue.php:906
3037
  msgid "Basic Widget"
3038
  msgstr ""
3039
 
3040
+ #: languages/vue.php:909
3041
  msgid "Overview Report Synopsis"
3042
  msgstr ""
3043
 
3044
+ #: languages/vue.php:912
3045
  msgid "Advanced Dashboard Widget"
3046
  msgstr ""
3047
 
3048
+ #: languages/vue.php:915
3049
  msgid "Includes the complete Overview report, Publisher reports and 6 different eCommerce reports"
3050
  msgstr ""
3051
 
3052
+ #: languages/vue.php:918
3053
  msgid "Publisher Reports"
3054
  msgstr ""
3055
 
3056
+ #: languages/vue.php:921
3057
  msgid "Advanced Publisher Reports & Tracking"
3058
  msgstr ""
3059
 
3060
+ #: languages/vue.php:924
3061
  msgid "View Top Landing/Exit Pages, Top Links, Demographics & Interests data and more"
3062
  msgstr ""
3063
 
3064
+ #: languages/vue.php:927
3065
  msgid "Custom Dimensions"
3066
  msgstr ""
3067
 
3068
+ #: languages/vue.php:930
3069
  msgid "Not Available"
3070
  msgstr ""
3071
 
3072
+ #: languages/vue.php:933
3073
  msgid "Complete Custom Dimensions Tracking"
3074
  msgstr ""
3075
 
3076
+ #: languages/vue.php:936
3077
  msgid "Track and measure by the Author, Post Type, Category, Tags, SEO Score, Focus Keyword, Logged-in User, User ID and Published Time of each post and page"
3078
  msgstr ""
3079
 
3080
+ #: languages/vue.php:942
3081
  msgid "Limited support"
3082
  msgstr ""
3083
 
3084
+ #: languages/vue.php:945
3085
  msgid "Priority Support"
3086
  msgstr ""
3087
 
3088
+ #: languages/vue.php:948
3089
  msgid "Get the most out of MonsterInsights by upgrading to Pro and unlocking all of the powerful features."
3090
  msgstr ""
3091
 
3092
+ #: languages/vue.php:951
3093
  msgid "Feature"
3094
  msgstr ""
3095
 
3096
+ #: languages/vue.php:954
3097
  msgid "Lite"
3098
  msgstr ""
3099
 
3100
+ #: languages/vue.php:957
3101
  msgid "Pro"
3102
  msgstr ""
3103
 
3104
+ #: languages/vue.php:961
3105
  msgid "Universal Tracking"
3106
  msgstr ""
3107
 
3108
+ #: languages/vue.php:964
3109
  msgid "Included"
3110
  msgstr ""
3111
 
3112
+ #: languages/vue.php:967
3113
  msgid "Custom Google Analytics Link Tracking"
3114
  msgstr ""
3115
 
3116
+ #: languages/vue.php:970
3117
  msgid "Standard Tracking"
3118
  msgstr ""
3119
 
3120
+ #: languages/vue.php:973
3121
  msgid "Advanced Tracking"
3122
  msgstr ""
3123
 
3124
+ #: languages/vue.php:976
3125
  msgid "Automatic tracking of outbound/external, file download, affiliate, email and telephone links and our simple Custom Lin