Google Analytics for WordPress by MonsterInsights - Version 5.0.6

Version Description

Release Date: September 17th, 2014

  • Bugfixes:

    • Fixed several notices.
    • Improved support for premium extensions to this plugin.
    • Fixed bug where on multi-site or subdirectory installs, settings wouldn't save.
    • Fix the tracking of downloads in ga.js tracking.
    • Fixed a bug where custom code would be output after the send pageview instead of before.
    • Fixed an empty delimiter warning.
  • Enhancements:

    • Improved admin icon.
    • Added a filter wpga_menu_on_top which, when returned false, moves the analytics menu down.
    • Added filters yoast-ga-push-array-ga-js and yoast-ga-push-array-universal to filter the push arrays.
Download this release

Release Info

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

Code changes from version 5.0.5 to 5.0.6

.gruntjshintrc DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "boss": true,
3
- "curly": true,
4
- "eqeqeq": true,
5
- "eqnull": true,
6
- "es3": true,
7
- "immed": true,
8
- "latedef": true,
9
- "newcap": true,
10
- "noarg": true,
11
- "quotmark": "single",
12
- "sub": true,
13
- "strict": true,
14
- "undef": true,
15
- "unused": true,
16
-
17
- "node": true
18
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.jscsrc DELETED
@@ -1,112 +0,0 @@
1
- {
2
- "requireSpacesInConditionalExpression": true,
3
- "requireSpacesInFunctionExpression": {
4
- "beforeOpeningCurlyBrace": true
5
- },
6
- "disallowSpacesInFunctionExpression": {
7
- "beforeOpeningRoundBrace": true
8
- },
9
- "requireMultipleVarDecl": "onevar",
10
- "requireSpacesInsideObjectBrackets": "all",
11
- "disallowSpaceAfterObjectKeys": true,
12
- "requireSpaceAfterBinaryOperators": [
13
- "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
14
- "&=", "|=", "^=", "+=",
15
-
16
- "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
17
- "|", "^", "&&", "||", "===", "==", ">=",
18
- "<=", "<", ">", "!=", "!=="
19
- ],
20
- "requireSpaceBeforeBinaryOperators": [
21
- "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
22
- "&=", "|=", "^=", "+=",
23
-
24
- "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
25
- "|", "^", "&&", "||", "===", "==", ">=",
26
- "<=", "<", ">", "!=", "!=="
27
- ],
28
- "disallowKeywords": ["with"],
29
- "disallowMultipleLineBreaks": true,
30
- "validateLineBreaks": "LF",
31
- "disallowMixedSpacesAndTabs": "smart",
32
- "disallowTrailingWhitespace": true,
33
-
34
- "requireCurlyBraces": [ "if", "else", "for", "while", "do", "try", "catch" ],
35
- "requireSpaceBeforeBlockStatements": true,
36
- "requireParenthesesAroundIIFE": true,
37
- "requireBlocksOnNewline": true,
38
- "requireRightStickedOperators": [],
39
- "requireOperatorBeforeLineBreak": [
40
- "?",
41
- "=",
42
- "+",
43
- "-",
44
- "/",
45
- "*",
46
- "==",
47
- "===",
48
- "!=",
49
- "!==",
50
- ">",
51
- ">=",
52
- "<",
53
- "<="
54
- ],
55
- "disallowLeftStickedOperators": [
56
- "?",
57
- "=",
58
- "+",
59
- "-",
60
- "/",
61
- "*",
62
- "==",
63
- "===",
64
- "!=",
65
- "!==",
66
- ">",
67
- ">=",
68
- "<",
69
- "<="
70
- ],
71
- "disallowRightStickedOperators": [
72
- "?",
73
- "=",
74
- "+",
75
- "/",
76
- "*",
77
- ":",
78
- "==",
79
- "===",
80
- "!=",
81
- "!==",
82
- ">",
83
- ">=",
84
- "<",
85
- "<="
86
- ],
87
- "requireLeftStickedOperators": [","],
88
- "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~"],
89
- "requireSpaceAfterPrefixUnaryOperators": ["!"],
90
- "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
91
- "requireCamelCaseOrUpperCaseIdentifiers": true,
92
- "disallowMultipleLineStrings": true,
93
- "validateQuoteMarks": "'",
94
- "validateIndentation": "\t",
95
- "requireLineFeedAtFileEnd": true,
96
- "requireDotNotation": true,
97
-
98
- "disallowTrailingComma": true,
99
- "disallowPaddingNewlinesInBlocks": true,
100
- "disallowEmptyBlocks": true,
101
- "disallowQuotedKeysInObjects": "allButReserved",
102
- "disallowDanglingUnderscores": true,
103
- "requireCommaBeforeLineBreak": true,
104
- "disallowKeywordsOnNewLine": ["else"],
105
- "requireCapitalizedConstructors": true,
106
- "safeContextKeyword": [ "that" ],
107
- "validateJSDoc": {
108
- "checkParamNames": true,
109
- "checkRedundantParams": true,
110
- "requireParamTypes": true
111
- }
112
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -1,6 +1,8 @@
1
  Google Analytics for WordPress
2
  ==============================
3
 
 
 
4
  Add Google Analytics to WordPress and be able to use all the powerful functions Google Analytics offers!
5
 
6
 
1
  Google Analytics for WordPress
2
  ==============================
3
 
4
+ [![Build Status](https://api.travis-ci.org/Yoast/google-analytics-for-wordpress.png?branch=master)](https://travis-ci.org/Yoast/google-analytics-for-wordpress)
5
+
6
  Add Google Analytics to WordPress and be able to use all the powerful functions Google Analytics offers!
7
 
8
 
admin/class-admin.php CHANGED
@@ -3,19 +3,17 @@
3
  * This class is for the backend, extendable for all child classes
4
  */
5
 
6
- require_once plugin_dir_path( __FILE__ ) . '/wp-gdata/wp-gdata.php';
7
 
8
  if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
9
 
10
- class Yoast_GA_Admin {
11
 
12
  private $form_namespace;
13
 
14
- public $options;
15
-
16
- private $form_prefix = 'ga_general';
17
-
18
  public function __construct() {
 
 
19
  add_action( 'plugins_loaded', array( $this, 'init_ga' ) );
20
  add_action( 'admin_init', array( $this, 'init_settings' ) );
21
  }
@@ -25,25 +23,17 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
25
  */
26
  public function init_ga() {
27
  add_action( 'admin_menu', array( $this, 'create_menu' ), 5 );
28
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
29
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
30
 
31
- add_filter( 'plugin_action_links_' . plugin_basename( GAWP_FILE ), array( $this, 'add_action_links' ), 10, 2 );
32
  }
33
 
34
  /**
35
  * Init function for the settings of GA
36
  */
37
  public function init_settings() {
38
- $this->options = get_option( 'yst_ga' );
39
-
40
- if ( false == $this->options ) {
41
- add_option( 'yst_ga', $this->default_ga_values() );
42
- $this->options = get_option( 'yst_ga' );
43
- }
44
 
45
- global $Yoast_GA_Options;
46
- if ( is_null( $Yoast_GA_Options->get_tracking_code() ) ) {
47
  add_action( 'admin_notices', array( $this, 'config_warning' ) );
48
  }
49
 
@@ -80,54 +70,6 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
80
  echo '<div class="error"><p>' . sprintf( __( 'Please configure your %sGoogle Analytics settings%s!', 'google-analytics-for-wordpress' ), '<a href="' . admin_url( 'admin.php?page=yst_ga_settings' ) . '">', '</a>' ) . '</p></div>';
81
  }
82
 
83
- /**
84
- * Set the default GA settings here
85
- * @return array
86
- */
87
- public function default_ga_values() {
88
- return array(
89
- $this->form_prefix => array(
90
- 'analytics_profile' => null,
91
- 'manual_ua_code' => 0,
92
- 'manual_ua_code_field' => null,
93
- 'track_internal_as_outbound' => null,
94
- 'track_internal_as_label' => null,
95
- 'track_outbound' => 0,
96
- 'anonymous_data' => 0,
97
- 'enable_universal' => 0,
98
- 'demographics' => 0,
99
- 'ignore_users' => array( 'editor' ),
100
- 'anonymize_ips' => null,
101
- 'track_download_as' => 'event',
102
- 'extensions_of_files' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
103
- 'track_full_url' => 'domain',
104
- 'subdomain_tracking' => null,
105
- 'tag_links_in_rss' => 0,
106
- 'allow_anchor' => 0,
107
- 'add_allow_linker' => 0,
108
- 'custom_code' => null,
109
- 'debug_mode' => 0,
110
- 'firebug_lite' => 0,
111
- )
112
- );
113
- }
114
-
115
- /**
116
- * Return the setting by name
117
- *
118
- * @param $name
119
- *
120
- * @return null
121
- */
122
- public function get_setting( $name ) {
123
-
124
- if ( isset( $this->options[ $this->form_prefix ][ $name ] ) ) {
125
- return $this->options[ $this->form_prefix ][ $name ];
126
- } else {
127
- return null;
128
- }
129
- }
130
-
131
  /**
132
  * This function saves the settings in the option field and returns a wp success message on success
133
  *
@@ -135,18 +77,18 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
135
  */
136
  public function save_settings( $data ) {
137
  foreach ( $data as $key => $value ) {
138
- $this->options[ $this->form_prefix ][ $key ] = $value;
139
  }
140
 
141
  // Check checkboxes, on a uncheck they won't be posted to this function
142
  $defaults = $this->default_ga_values();
143
- foreach ( $defaults['ga_general'] as $key => $value ) {
144
  if ( ! isset( $data[ $key ] ) ) {
145
- $this->options[ $this->form_prefix ][ $key ] = $value;
146
  }
147
  }
148
 
149
- if ( update_option( 'yst_ga', $this->options ) ) {
150
  // Success!
151
  } else {
152
  // Fail..
@@ -154,31 +96,16 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
154
 
155
  }
156
 
157
- /**
158
- * Get the singleton instance of this class
159
- *
160
- * @return object
161
- */
162
- public static function get_instance() {
163
- if ( ! ( self::$instance instanceof self ) ) {
164
- self::$instance = new self();
165
- }
166
-
167
- return self::$instance;
168
- }
169
-
170
  /**
171
  * Add a link to the settings page to the plugins list
172
  *
173
- * @staticvar string $this_plugin holds the directory & filename for the plugin
174
  *
175
- * @param array $links array of links for the plugins, adapted when the current plugin is found.
176
- * @param string $file the filename for the current plugin, which the filter loops through.
177
- *
178
- * @return array $links
179
  */
180
- function add_action_links( $links, $file ) {
181
  // add link to knowledgebase
 
182
  $faq_link = '<a title="Yoast Knowledge Base" href="http://kb.yoast.com/category/43-google-analytics-for-wordpress">' . __( 'FAQ', 'google-analytics-for-wordpress' ) . '</a>';
183
  array_unshift( $links, $faq_link );
184
 
@@ -193,12 +120,22 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
193
  *
194
  * @todo, we need to implement a new icon for this, currently we're using the WP seo icon
195
  */
196
- public function create_menu( $param = null ) {
 
 
 
 
 
 
 
 
 
 
197
  // Add main page
198
  add_menu_page( __( 'Yoast Google Analytics:', 'google-analytics-for-wordpress' ) . ' ' . __( 'General Settings', 'google-analytics-for-wordpress' ), __( 'Analytics', 'google-analytics-for-wordpress' ), 'manage_options', 'yst_ga_dashboard', array(
199
  $this,
200
- 'load_page'
201
- ), plugins_url( 'img/yoast-icon.png', GAWP_FILE ), '2.00013467543' );
202
 
203
  // Sub menu pages
204
  $submenu_pages = array(
@@ -209,7 +146,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
209
  'manage_options',
210
  'yst_ga_dashboard',
211
  array( $this, 'load_page' ),
212
- array( array( $this, 'yst_ga_dashboard' ) )
213
  ),
214
  array(
215
  'yst_ga_dashboard',
@@ -218,7 +155,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
218
  'manage_options',
219
  'yst_ga_settings',
220
  array( $this, 'load_page' ),
221
- array( array( $this, 'yst_ga_settings' ) )
222
  ),
223
  array(
224
  'yst_ga_dashboard',
@@ -227,55 +164,80 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
227
  'manage_options',
228
  'yst_ga_licenses',
229
  array( $this, 'load_page' ),
230
- null
231
  ),
232
  );
233
 
234
  if ( count( $submenu_pages ) ) {
235
  foreach ( $submenu_pages as $submenu_page ) {
236
  // Add submenu page
237
- add_submenu_page( $submenu_page[0], $submenu_page[1], $submenu_page[2], $submenu_page[3], $submenu_page[4], $submenu_page[5] );
 
 
 
 
 
238
  }
239
  }
240
  }
241
 
242
  /**
243
- * Add the scripts to the admin head
 
 
244
  *
245
- * @todo add minified JS files
 
 
 
 
 
 
 
 
 
 
246
  */
247
  public function enqueue_scripts() {
248
- wp_enqueue_script( 'yoast_ga_admin', GAWP_URL . 'js/yoast_ga_admin.js' );
 
 
 
249
  }
250
 
251
  /**
252
  * Add the styles in the admin head
253
- *
254
- * @todo add minified CSS files
255
  */
256
  public function enqueue_styles() {
257
- wp_enqueue_style( 'yoast_ga_styles', GAWP_URL . 'css/yoast_ga_styles.css' );
 
 
 
 
 
 
 
 
258
  }
259
 
260
  /**
261
  * Load the page of a menu item in the GA plugin
262
  */
263
  public function load_page() {
264
-
265
- require_once GAWP_PATH . 'admin/class-admin-ga-js.php';
266
 
267
  if ( isset( $_GET['page'] ) ) {
268
  switch ( $_GET['page'] ) {
269
  case 'yst_ga_settings':
270
- require_once( GAWP_PATH . 'admin/pages/settings.php' );
271
 
272
  break;
273
  case 'yst_ga_licenses':
274
- require_once( GAWP_PATH . 'admin/pages/extensions.php' );
275
  break;
276
  case 'yst_ga_dashboard':
277
  default:
278
- require_once( GAWP_PATH . 'admin/pages/dashboard.php' );
279
  break;
280
  }
281
  }
@@ -284,14 +246,14 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
284
  /**
285
  * Create a form element to init a form
286
  *
287
- * @param $namespace
288
  *
289
  * @return string
290
  */
291
  public function create_form( $namespace ) {
292
  $this->form_namespace = $namespace;
293
 
294
- $action = $_SERVER['PHP_SELF'];
295
  if ( isset( $_GET['page'] ) ) {
296
  $action .= '?page=' . $_GET['page'];
297
  }
@@ -307,7 +269,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
307
  *
308
  * @return null|string
309
  */
310
- public function end_form( $button_label = "Save changes", $name = 'submit' ) {
311
  $output = null;
312
  $output .= '<div class="ga-form ga-form-input">';
313
  $output .= '<input type="submit" name="ga-form-' . $name . '" value="' . $button_label . '" class="button button-primary ga-form-submit" id="yoast-ga-form-submit-' . $this->form_namespace . '">';
@@ -319,11 +281,11 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
319
  /**
320
  * Create a input form element with our labels and wrap them
321
  *
322
- * @param string $type
323
- * @param null $title
324
- * @param null $name
325
- * @param null $text_label
326
- * @param null $description
327
  *
328
  * @return null|string
329
  */
@@ -337,16 +299,16 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
337
  $input .= '<label class="ga-form ga-form-' . $type . '-label ga-form-label-left" id="yoast-ga-form-label-' . $type . '-' . $this->form_namespace . '-' . $id . '" />' . $title . ':</label>';
338
  }
339
 
340
- if ( $type == 'checkbox' && $this->get_setting( $name ) == 1 ) {
341
  $input .= '<input type="' . $type . '" class="ga-form ga-form-checkbox" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="1" checked="checked" />';
342
  } elseif ( $type == 'checkbox' ) {
343
  $input .= '<input type="' . $type . '" class="ga-form ga-form-checkbox" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="1" />';
344
  } else {
345
- $input .= '<input type="' . $type . '" class="ga-form ga-form-' . $type . '" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="' . stripslashes( $this->get_setting( $name ) ) . '" />';
346
  }
347
 
348
  if ( ! is_null( $text_label ) ) {
349
- $input .= '<label class="ga-form ga-form-' . $type . '-label" id="yoast-ga-form-label-' . $type . '-textlabel-' . $this->form_namespace . '-' . $id . '" for="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" />' . __( $text_label, 'google-analytics-for-wordpress' ) . '</label>';
350
  }
351
 
352
  $input .= '</div>';
@@ -355,7 +317,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
355
  if ( ! is_null( $description ) ) {
356
  $input .= '<div class="ga-form ga-form-input">';
357
  $input .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-description-select-' . $this->form_namespace . '-' . $id . '" />&nbsp;</label>';
358
- $input .= '<span class="ga-form ga-form-description">' . __( $description, 'google-analytics-for-wordpress' ) . '</span>';
359
  $input .= '</div>';
360
  }
361
 
@@ -365,11 +327,11 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
365
  /**
366
  * Generate a select box
367
  *
368
- * @param $title
369
- * @param $name
370
- * @param $values
371
- * @param null $description
372
- * @param bool $multiple
373
  *
374
  * @return null|string
375
  */
@@ -379,7 +341,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
379
  $id = str_replace( ']', '', $id );
380
  $select .= '<div class="ga-form ga-form-input">';
381
  if ( ! is_null( $title ) ) {
382
- $select .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-label-select-' . $this->form_namespace . '-' . $id . '" />' . __( $title, 'google-analytics-for-wordpress' ) . ':</label>';
383
  }
384
 
385
  if ( $multiple ) {
@@ -389,14 +351,14 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
389
  }
390
  if ( count( $values ) >= 1 ) {
391
  foreach ( $values as $value ) {
392
- if ( is_array( $this->get_setting( $name ) ) ) {
393
- if ( in_array( $value['id'], $this->get_setting( $name ) ) ) {
394
  $select .= '<option value="' . $value['id'] . '" selected="selected">' . stripslashes( $value['name'] ) . '</option>';
395
  } else {
396
  $select .= '<option value="' . $value['id'] . '">' . stripslashes( $value['name'] ) . '</option>';
397
  }
398
  } else {
399
- $select .= '<option value="' . $value['id'] . '" ' . selected( $this->get_setting( $name ), $value['id'], false ) . '>' . stripslashes( $value['name'] ) . '</option>';
400
  }
401
  }
402
  }
@@ -417,20 +379,20 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
417
  /**
418
  * Generate a textarea field
419
  *
420
- * @param $title
421
- * @param $name
422
- * @param null $description
423
  *
424
  * @return null|string
425
  */
426
  public function textarea( $title, $name, $description = null ) {
427
  $text = null;
428
- $id = $this->form_prefix . '_' . $name;
429
  $text .= '<div class="ga-form ga-form-input">';
430
  if ( ! is_null( $title ) ) {
431
  $text .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-label-select-' . $this->form_namespace . '-' . $id . '" />' . __( $title, 'google-analytics-for-wordpress' ) . ':</label>';
432
  }
433
- $text .= '<textarea rows="5" cols="60" name="' . $name . '" id="yoast-ga-form-textarea-' . $this->form_namespace . '-' . $id . '">' . stripslashes( $this->get_setting( $name ) ) . '</textarea>';
434
  $text .= '</div>';
435
 
436
  // If we get a description, append it to this select field in a new row
@@ -446,17 +408,11 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
446
 
447
  /**
448
  * Get the Google Analytics profiles which are in this google account
 
449
  * @return array
450
- * @todo OAuth connection to Google.com?
451
  */
452
  public function get_profiles() {
453
 
454
- // Enqueue the chosen css file
455
- wp_enqueue_style( 'chosen_css', plugins_url( 'js/chosen.css', GAWP_FILE ) );
456
-
457
- // Eqneue the chosen js file
458
- wp_enqueue_script( 'chosen_js', plugins_url( 'js/chosen.jquery.min.js', GAWP_FILE ), array(), false, true );
459
-
460
  $option_name = 'yst_ga_api';
461
  $options = get_option( $option_name );
462
  $return = array();
@@ -476,7 +432,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
476
  if ( $http_code == 200 ) {
477
  $options['ga_api_response'] = array(
478
  'response' => array( 'code' => $http_code ),
479
- 'body' => $response
480
  );
481
  update_option( $option_name, $options );
482
  } else {
@@ -510,7 +466,6 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
510
  'title' => $title,
511
  );
512
  }
513
-
514
  }
515
  } else {
516
  if ( $xml_reader->link['href'] == 'https://www.google.com/analytics/feeds/accounts/default' ) {
@@ -532,7 +487,6 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
532
  'title' => $title,
533
  );
534
  }
535
-
536
  }
537
  }
538
  }
@@ -559,18 +513,17 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
559
  /**
560
  * Sorting the array in alphabetic order
561
  *
562
- * @param $a
563
- * @param $b
564
  *
565
  * @return int
566
  */
567
  public function sort_profiles( $a, $b ) {
568
- return strcmp( $a["title"], $b["title"] );
569
  }
570
 
571
  /**
572
  * Checks if there is a callback or reauth to get token from Google Analytics api
573
- *
574
  */
575
  private function connect_with_google_analytics() {
576
 
@@ -582,7 +535,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
582
  $gdata = new WP_GData(
583
  array(
584
  'scope' => 'https://www.google.com/analytics/feeds/',
585
- 'xoauth_displayname' => 'Google Analytics by Yoast'
586
  ),
587
  $o['ga_oauth']['oauth_token'],
588
  $o['ga_oauth']['oauth_token_secret']
@@ -604,7 +557,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
604
  $gdata = new WP_GData(
605
  array(
606
  'scope' => 'https://www.google.com/analytics/feeds/',
607
- 'xoauth_displayname' => 'Google Analytics by Yoast'
608
  )
609
  );
610
 
@@ -631,6 +584,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
631
 
632
  /**
633
  * Get the user roles of this WordPress blog
 
634
  * @return array
635
  */
636
  public function get_userroles() {
@@ -638,6 +592,12 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
638
 
639
  $all_roles = $wp_roles->roles;
640
  $roles = array();
 
 
 
 
 
 
641
  $editable_roles = apply_filters( 'editable_roles', $all_roles );
642
  foreach ( $editable_roles as $id => $name ) {
643
  $roles[] = array(
@@ -651,6 +611,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
651
 
652
  /**
653
  * Get types of how we can track downloads
 
654
  * @return array
655
  */
656
  public function track_download_types() {
@@ -662,6 +623,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
662
 
663
  /**
664
  * Get options for the track full url or links setting
 
665
  * @return array
666
  */
667
  public function get_track_full_url() {
@@ -675,7 +637,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
675
  * Render the admin page head for the GA Plugin
676
  */
677
  public function content_head() {
678
- require( "views/content_head.php" );
679
  }
680
 
681
  /**
@@ -685,23 +647,23 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
685
  $banners = array();
686
  $banners[] = array(
687
  'url' => 'https://yoast.com/hire-us/website-review/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
688
- 'banner' => GAWP_URL . 'img/banner-website-review.png',
689
- 'title' => 'Get a website review by Yoast'
690
  );
691
  $banners[] = array(
692
  'url' => 'https://yoast.com/wordpress/plugins/seo-premium/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
693
- 'banner' => GAWP_URL . 'img/banner-premium-seo.png',
694
- 'title' => 'Get WordPress SEO premium'
695
  );
696
  $banners[] = array(
697
  'url' => 'https://yoast.com/ebook-optimize-wordpress-site/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
698
- 'banner' => GAWP_URL . 'img/eBook_261x130.png',
699
- 'title' => 'Get the Yoast ebook!'
700
  );
701
  $banners[] = array(
702
  'url' => 'https://yoast.com/wordpress/plugins/local-seo/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
703
- 'banner' => GAWP_URL . 'img/banner-local-seo.png',
704
- 'title' => 'Get WooCommerce integrated in your Analytics'
705
  );
706
 
707
  shuffle( $banners );
@@ -713,7 +675,7 @@ if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
713
  echo '</pre></div></div>';
714
  }
715
 
716
- require( "views/content_footer.php" );
717
  }
718
 
719
  }
3
  * This class is for the backend, extendable for all child classes
4
  */
5
 
6
+ require_once 'wp-gdata/wp-gdata.php';
7
 
8
  if ( ! class_exists( 'Yoast_GA_Admin' ) ) {
9
 
10
+ class Yoast_GA_Admin extends Yoast_GA_Options {
11
 
12
  private $form_namespace;
13
 
 
 
 
 
14
  public function __construct() {
15
+ parent::__construct();
16
+
17
  add_action( 'plugins_loaded', array( $this, 'init_ga' ) );
18
  add_action( 'admin_init', array( $this, 'init_settings' ) );
19
  }
23
  */
24
  public function init_ga() {
25
  add_action( 'admin_menu', array( $this, 'create_menu' ), 5 );
 
 
26
 
27
+ add_filter( 'plugin_action_links_' . plugin_basename( GAWP_FILE ), array( $this, 'add_action_links' ) );
28
  }
29
 
30
  /**
31
  * Init function for the settings of GA
32
  */
33
  public function init_settings() {
34
+ $this->options = $this->get_options();
 
 
 
 
 
35
 
36
+ if ( is_null( $this->get_tracking_code() ) ) {
 
37
  add_action( 'admin_notices', array( $this, 'config_warning' ) );
38
  }
39
 
70
  echo '<div class="error"><p>' . sprintf( __( 'Please configure your %sGoogle Analytics settings%s!', 'google-analytics-for-wordpress' ), '<a href="' . admin_url( 'admin.php?page=yst_ga_settings' ) . '">', '</a>' ) . '</p></div>';
71
  }
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  /**
74
  * This function saves the settings in the option field and returns a wp success message on success
75
  *
77
  */
78
  public function save_settings( $data ) {
79
  foreach ( $data as $key => $value ) {
80
+ $this->options[ $key ] = $value;
81
  }
82
 
83
  // Check checkboxes, on a uncheck they won't be posted to this function
84
  $defaults = $this->default_ga_values();
85
+ foreach ( $defaults[ $this->option_prefix ] as $key => $value ) {
86
  if ( ! isset( $data[ $key ] ) ) {
87
+ $this->options[ $key ] = $value;
88
  }
89
  }
90
 
91
+ if ( $this->update_option( $this->options ) ) {
92
  // Success!
93
  } else {
94
  // Fail..
96
 
97
  }
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  /**
100
  * Add a link to the settings page to the plugins list
101
  *
102
+ * @param array $links array of links for the plugins, adapted when the current plugin is found.
103
  *
104
+ * @return array $links
 
 
 
105
  */
106
+ function add_action_links( $links ) {
107
  // add link to knowledgebase
108
+ // @todo UTM link fix
109
  $faq_link = '<a title="Yoast Knowledge Base" href="http://kb.yoast.com/category/43-google-analytics-for-wordpress">' . __( 'FAQ', 'google-analytics-for-wordpress' ) . '</a>';
110
  array_unshift( $links, $faq_link );
111
 
120
  *
121
  * @todo, we need to implement a new icon for this, currently we're using the WP seo icon
122
  */
123
+ public function create_menu() {
124
+ /**
125
+ * Filter: 'wpga_menu_on_top' - Allows filtering of menu location of the GA plugin, if false is returned, it moves to bottom.
126
+ *
127
+ * @api book unsigned
128
+ */
129
+ $on_top = apply_filters( 'wpga_menu_on_top', true );
130
+
131
+ // Base 64 encoded SVG image
132
+ $icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCIgWw0KCTwhRU5USVRZIG5zX2Zsb3dzICJodHRwOi8vbnMuYWRvYmUuY29tL0Zsb3dzLzEuMC8iPg0KCTwhRU5USVRZIG5zX2V4dGVuZCAiaHR0cDovL25zLmFkb2JlLmNvbS9FeHRlbnNpYmlsaXR5LzEuMC8iPg0KCTwhRU5USVRZIG5zX2FpICJodHRwOi8vbnMuYWRvYmUuY29tL0Fkb2JlSWxsdXN0cmF0b3IvMTAuMC8iPg0KCTwhRU5USVRZIG5zX2dyYXBocyAiaHR0cDovL25zLmFkb2JlLmNvbS9HcmFwaHMvMS4wLyI+DQpdPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYWFnXzEiIHhtbG5zOng9IiZuc19leHRlbmQ7IiB4bWxuczppPSImbnNfYWk7IiB4bWxuczpncmFwaD0iJm5zX2dyYXBoczsiDQoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmE9Imh0dHA6Ly9ucy5hZG9iZS5jb20vQWRvYmVTVkdWaWV3ZXJFeHRlbnNpb25zLzMuMC8iDQoJIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNDAgMzEuODkiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDQwIDMxLjg5IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KPHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTQwLDEyLjUyNEM0MCw1LjYwOCwzMS40NjksMCwyMCwwQzguNTMsMCwwLDUuNjA4LDAsMTIuNTI0YzAsNS41Niw1LjI0MywxMC4yNzIsMTMuNTU3LDExLjkwN3YtNC4wNjUNCgljMCwwLDAuMDQtMS0wLjI4LTEuOTJjLTAuMzItMC45MjEtMS43Ni0zLjAwMS0xLjc2LTUuMTIxYzAtMi4xMjEsMi41NjEtOS41NjMsNS4xMjItMTAuNDQ0Yy0wLjQsMS4yMDEtMC4zMiw3LjY4My0wLjMyLDcuNjgzDQoJczEuNCwyLjcyLDQuNjQxLDIuNzJjMy4yNDIsMCw0LjUxMS0xLjc2LDQuNzE1LTIuMmMwLjIwNi0wLjQ0LDAuODQ2LTguNzIzLDAuODQ2LTguNzIzczQuMDgyLDQuNDAyLDMuNjgyLDkuMzYzDQoJYy0wLjQwMSw0Ljk2Mi00LjQ4Miw3LjIwMy02LjEyMiw5LjEyM2MtMS4yODYsMS41MDUtMi4yMjQsMy4xMy0yLjYyOSw0LjE2OGMwLjgwMS0wLjAzNCwxLjU4Ny0wLjA5OCwyLjM2MS0wLjE4NGw5LjE1MSw3LjA1OQ0KCWwtNC44ODQtNy44M0MzNS41MzUsMjIuMTYxLDQwLDE3LjcxMyw0MCwxMi41MjR6Ii8+DQo8L2c+DQo8L3N2Zz4=';
133
+
134
  // Add main page
135
  add_menu_page( __( 'Yoast Google Analytics:', 'google-analytics-for-wordpress' ) . ' ' . __( 'General Settings', 'google-analytics-for-wordpress' ), __( 'Analytics', 'google-analytics-for-wordpress' ), 'manage_options', 'yst_ga_dashboard', array(
136
  $this,
137
+ 'load_page',
138
+ ), $icon_svg, $on_top ? '2.00013467543': '100.00013467543' );
139
 
140
  // Sub menu pages
141
  $submenu_pages = array(
146
  'manage_options',
147
  'yst_ga_dashboard',
148
  array( $this, 'load_page' ),
149
+ array( array( $this, 'yst_ga_dashboard' ) ),
150
  ),
151
  array(
152
  'yst_ga_dashboard',
155
  'manage_options',
156
  'yst_ga_settings',
157
  array( $this, 'load_page' ),
158
+ array( array( $this, 'yst_ga_settings' ) ),
159
  ),
160
  array(
161
  'yst_ga_dashboard',
164
  'manage_options',
165
  'yst_ga_licenses',
166
  array( $this, 'load_page' ),
167
+ array( array( $this, 'yst_ga_licenses' ) ),
168
  ),
169
  );
170
 
171
  if ( count( $submenu_pages ) ) {
172
  foreach ( $submenu_pages as $submenu_page ) {
173
  // Add submenu page
174
+ $page = add_submenu_page( $submenu_page[0], $submenu_page[1], $submenu_page[2], $submenu_page[3], $submenu_page[4], $submenu_page[5] );
175
+ add_action( 'admin_print_styles-' . $page, array( $this, 'enqueue_styles' ) );
176
+ if ( 'yst_ga_settings' === $submenu_page[4] || 'yst_ga_licenses' === $submenu_page[4] ) {
177
+ add_action( 'admin_print_styles-' . $page, array( $this, 'enqueue_settings_styles' ) );
178
+ add_action( 'admin_print_scripts-' . $page, array( $this, 'enqueue_scripts' ) );
179
+ }
180
  }
181
  }
182
  }
183
 
184
  /**
185
+ * Check whether we can include the minified version or not
186
+ *
187
+ * @param string $ext
188
  *
189
+ * @return string
190
+ */
191
+ private function file_ext( $ext ) {
192
+ if ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) {
193
+ $ext = '.min' . $ext;
194
+ }
195
+ return $ext;
196
+ }
197
+
198
+ /**
199
+ * Add the scripts to the admin head
200
  */
201
  public function enqueue_scripts() {
202
+ wp_enqueue_script( 'yoast_ga_admin', $this->plugin_url . 'js/yoast_ga_admin' . $this->file_ext( '.js' ) );
203
+
204
+ // Eqneue the chosen js file
205
+ wp_enqueue_script( 'chosen_js', plugins_url( 'js/chosen.jquery.min.js', GAWP_FILE ), array(), false, true );
206
  }
207
 
208
  /**
209
  * Add the styles in the admin head
 
 
210
  */
211
  public function enqueue_styles() {
212
+ wp_enqueue_style( 'yoast_ga_styles', $this->plugin_url . 'css/yoast_ga_styles' . $this->file_ext( '.css' ) );
213
+ }
214
+
215
+ /**
216
+ * Enqueues the settings page specific styles
217
+ */
218
+ public function enqueue_settings_styles() {
219
+ // Enqueue the chosen css file
220
+ wp_enqueue_style( 'chosen_css', $this->plugin_url . 'css/chosen' . $this->file_ext( '.css' ) );
221
  }
222
 
223
  /**
224
  * Load the page of a menu item in the GA plugin
225
  */
226
  public function load_page() {
227
+ require_once $this->plugin_path . 'admin/class-admin-ga-js.php';
 
228
 
229
  if ( isset( $_GET['page'] ) ) {
230
  switch ( $_GET['page'] ) {
231
  case 'yst_ga_settings':
232
+ require_once( $this->plugin_path . 'admin/pages/settings.php' );
233
 
234
  break;
235
  case 'yst_ga_licenses':
236
+ require_once( $this->plugin_path . 'admin/pages/extensions.php' );
237
  break;
238
  case 'yst_ga_dashboard':
239
  default:
240
+ require_once( $this->plugin_path . 'admin/pages/dashboard.php' );
241
  break;
242
  }
243
  }
246
  /**
247
  * Create a form element to init a form
248
  *
249
+ * @param string $namespace
250
  *
251
  * @return string
252
  */
253
  public function create_form( $namespace ) {
254
  $this->form_namespace = $namespace;
255
 
256
+ $action = admin_url( 'admin.php' );
257
  if ( isset( $_GET['page'] ) ) {
258
  $action .= '?page=' . $_GET['page'];
259
  }
269
  *
270
  * @return null|string
271
  */
272
+ public function end_form( $button_label = 'Save changes', $name = 'submit' ) {
273
  $output = null;
274
  $output .= '<div class="ga-form ga-form-input">';
275
  $output .= '<input type="submit" name="ga-form-' . $name . '" value="' . $button_label . '" class="button button-primary ga-form-submit" id="yoast-ga-form-submit-' . $this->form_namespace . '">';
281
  /**
282
  * Create a input form element with our labels and wrap them
283
  *
284
+ * @param string $type
285
+ * @param null|string $title
286
+ * @param null|string $name
287
+ * @param null|string $text_label
288
+ * @param null|string $description
289
  *
290
  * @return null|string
291
  */
299
  $input .= '<label class="ga-form ga-form-' . $type . '-label ga-form-label-left" id="yoast-ga-form-label-' . $type . '-' . $this->form_namespace . '-' . $id . '" />' . $title . ':</label>';
300
  }
301
 
302
+ if ( $type == 'checkbox' && $this->options[ $name ] == 1 ) {
303
  $input .= '<input type="' . $type . '" class="ga-form ga-form-checkbox" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="1" checked="checked" />';
304
  } elseif ( $type == 'checkbox' ) {
305
  $input .= '<input type="' . $type . '" class="ga-form ga-form-checkbox" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="1" />';
306
  } else {
307
+ $input .= '<input type="' . $type . '" class="ga-form ga-form-' . $type . '" id="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" name="' . $name . '" value="' . stripslashes( $this->options[ $name ] ) . '" />';
308
  }
309
 
310
  if ( ! is_null( $text_label ) ) {
311
+ $input .= '<label class="ga-form ga-form-' . $type . '-label" id="yoast-ga-form-label-' . $type . '-textlabel-' . $this->form_namespace . '-' . $id . '" for="yoast-ga-form-' . $type . '-' . $this->form_namespace . '-' . $id . '" />' . $text_label . '</label>';
312
  }
313
 
314
  $input .= '</div>';
317
  if ( ! is_null( $description ) ) {
318
  $input .= '<div class="ga-form ga-form-input">';
319
  $input .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-description-select-' . $this->form_namespace . '-' . $id . '" />&nbsp;</label>';
320
+ $input .= '<span class="ga-form ga-form-description">' . $description . '</span>';
321
  $input .= '</div>';
322
  }
323
 
327
  /**
328
  * Generate a select box
329
  *
330
+ * @param string $title
331
+ * @param string $name
332
+ * @param array $values
333
+ * @param null|string $description
334
+ * @param bool $multiple
335
  *
336
  * @return null|string
337
  */
341
  $id = str_replace( ']', '', $id );
342
  $select .= '<div class="ga-form ga-form-input">';
343
  if ( ! is_null( $title ) ) {
344
+ $select .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-label-select-' . $this->form_namespace . '-' . $id . '" />' . $title . ':</label>';
345
  }
346
 
347
  if ( $multiple ) {
351
  }
352
  if ( count( $values ) >= 1 ) {
353
  foreach ( $values as $value ) {
354
+ if ( is_array( $this->options[ $name ] ) ) {
355
+ if ( in_array( $value['id'], $this->options[ $name ] ) ) {
356
  $select .= '<option value="' . $value['id'] . '" selected="selected">' . stripslashes( $value['name'] ) . '</option>';
357
  } else {
358
  $select .= '<option value="' . $value['id'] . '">' . stripslashes( $value['name'] ) . '</option>';
359
  }
360
  } else {
361
+ $select .= '<option value="' . $value['id'] . '" ' . selected( $this->options[ $name ], $value['id'], false ) . '>' . stripslashes( $value['name'] ) . '</option>';
362
  }
363
  }
364
  }
379
  /**
380
  * Generate a textarea field
381
  *
382
+ * @param string $title
383
+ * @param string $name
384
+ * @param null|string $description
385
  *
386
  * @return null|string
387
  */
388
  public function textarea( $title, $name, $description = null ) {
389
  $text = null;
390
+ $id = $this->option_prefix . '_' . $name;
391
  $text .= '<div class="ga-form ga-form-input">';
392
  if ( ! is_null( $title ) ) {
393
  $text .= '<label class="ga-form ga-form-select-label ga-form-label-left" id="yoast-ga-form-label-select-' . $this->form_namespace . '-' . $id . '" />' . __( $title, 'google-analytics-for-wordpress' ) . ':</label>';
394
  }
395
+ $text .= '<textarea rows="5" cols="60" name="' . $name . '" id="yoast-ga-form-textarea-' . $this->form_namespace . '-' . $id . '">' . stripslashes( $this->options[ $name ] ) . '</textarea>';
396
  $text .= '</div>';
397
 
398
  // If we get a description, append it to this select field in a new row
408
 
409
  /**
410
  * Get the Google Analytics profiles which are in this google account
411
+ *
412
  * @return array
 
413
  */
414
  public function get_profiles() {
415
 
 
 
 
 
 
 
416
  $option_name = 'yst_ga_api';
417
  $options = get_option( $option_name );
418
  $return = array();
432
  if ( $http_code == 200 ) {
433
  $options['ga_api_response'] = array(
434
  'response' => array( 'code' => $http_code ),
435
+ 'body' => $response,
436
  );
437
  update_option( $option_name, $options );
438
  } else {
466
  'title' => $title,
467
  );
468
  }
 
469
  }
470
  } else {
471
  if ( $xml_reader->link['href'] == 'https://www.google.com/analytics/feeds/accounts/default' ) {
487
  'title' => $title,
488
  );
489
  }
 
490
  }
491
  }
492
  }
513
  /**
514
  * Sorting the array in alphabetic order
515
  *
516
+ * @param string $a
517
+ * @param string $b
518
  *
519
  * @return int
520
  */
521
  public function sort_profiles( $a, $b ) {
522
+ return strcmp( $a['title'], $b['title'] );
523
  }
524
 
525
  /**
526
  * Checks if there is a callback or reauth to get token from Google Analytics api
 
527
  */
528
  private function connect_with_google_analytics() {
529
 
535
  $gdata = new WP_GData(
536
  array(
537
  'scope' => 'https://www.google.com/analytics/feeds/',
538
+ 'xoauth_displayname' => 'Google Analytics by Yoast',
539
  ),
540
  $o['ga_oauth']['oauth_token'],
541
  $o['ga_oauth']['oauth_token_secret']
557
  $gdata = new WP_GData(
558
  array(
559
  'scope' => 'https://www.google.com/analytics/feeds/',
560
+ 'xoauth_displayname' => 'Google Analytics by Yoast',
561
  )
562
  );
563
 
584
 
585
  /**
586
  * Get the user roles of this WordPress blog
587
+ *
588
  * @return array
589
  */
590
  public function get_userroles() {
592
 
593
  $all_roles = $wp_roles->roles;
594
  $roles = array();
595
+
596
+ /**
597
+ * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
598
+ *
599
+ * @api array $all_roles
600
+ */
601
  $editable_roles = apply_filters( 'editable_roles', $all_roles );
602
  foreach ( $editable_roles as $id => $name ) {
603
  $roles[] = array(
611
 
612
  /**
613
  * Get types of how we can track downloads
614
+ *
615
  * @return array
616
  */
617
  public function track_download_types() {
623
 
624
  /**
625
  * Get options for the track full url or links setting
626
+ *
627
  * @return array
628
  */
629
  public function get_track_full_url() {
637
  * Render the admin page head for the GA Plugin
638
  */
639
  public function content_head() {
640
+ require 'views/content_head.php';
641
  }
642
 
643
  /**
647
  $banners = array();
648
  $banners[] = array(
649
  'url' => 'https://yoast.com/hire-us/website-review/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
650
+ 'banner' => $this->plugin_url . 'img/banner-website-review.png',
651
+ 'title' => 'Get a website review by Yoast',
652
  );
653
  $banners[] = array(
654
  'url' => 'https://yoast.com/wordpress/plugins/seo-premium/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
655
+ 'banner' => $this->plugin_url . 'img/banner-premium-seo.png',
656
+ 'title' => 'Get WordPress SEO premium',
657
  );
658
  $banners[] = array(
659
  'url' => 'https://yoast.com/ebook-optimize-wordpress-site/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
660
+ 'banner' => $this->plugin_url . 'img/eBook_261x130.png',
661
+ 'title' => 'Get the Yoast ebook!',
662
  );
663
  $banners[] = array(
664
  'url' => 'https://yoast.com/wordpress/plugins/local-seo/#utm_medium=banner&utm_source=gawp-config&utm_campaign=wpgaplugin',
665
+ 'banner' => $this->plugin_url . 'img/banner-local-seo.png',
666
+ 'title' => 'Get WooCommerce integrated in your Analytics',
667
  );
668
 
669
  shuffle( $banners );
675
  echo '</pre></div></div>';
676
  }
677
 
678
+ require 'views/content-footer.php';
679
  }
680
 
681
  }
admin/pages/extensions.php CHANGED
@@ -2,20 +2,67 @@
2
  global $yoast_ga_admin;
3
 
4
  echo $yoast_ga_admin->content_head();
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  ?>
6
  <h2 id="yoast_ga_title"><?php echo __( 'Yoast Google Analytics: Extensions', 'google-analytics-for-wordpress' ); ?></h2>
7
 
8
- <div id="extensions" class="wpseotab">
9
- <div class="extension ecommerce">
10
- <a target="_blank" href="https://yoast.com/wordpress/plugins/seo-premium/#utm_medium=banner&utm_source=gawp-config&utm_campaign=extension-page-banners">
11
- <h3>Google Analytics<br />E-Commerce tracking</h3>
12
- </a>
13
- <p>Track your E-Commerce data and transactions with this E-Commerce extension for Google Analytics.</p>
14
- <p><a target="_blank" href="https://yoast.com/wordpress/plugins/ga-ecommerce-edd/#utm_medium=banner&utm_source=gawp-config&utm_campaign=extension-page-banners" class="button-primary">
15
- Get this extension </a></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  </div>
17
  </div>
18
  <div class="clear"></div>
 
19
  <?php
20
  echo $yoast_ga_admin->content_footer();
21
  ?>
2
  global $yoast_ga_admin;
3
 
4
  echo $yoast_ga_admin->content_head();
5
+
6
+ $has_extensions = false;
7
+
8
+ $extensions = array(
9
+ 'ecommerce' => (object) array(
10
+ 'url' => 'https://yoast.com/wordpress/plugins/google-analytics/',
11
+ 'title' => __( 'Google Analytics', 'google-analytics-for-wordpress' ) . '<br />' . __( 'E-Commerce tracking', 'google-analytics-for-wordpress' ),
12
+ 'desc' => __( 'Track your E-Commerce data and transactions with this E-Commerce extension for Google Analytics.', 'google-analytics-for-wordpress' ),
13
+ 'status' => 'uninstalled',
14
+ ),
15
+ );
16
+
17
+ $extensions = apply_filters( 'yst_ga_extension_status', $extensions );
18
  ?>
19
  <h2 id="yoast_ga_title"><?php echo __( 'Yoast Google Analytics: Extensions', 'google-analytics-for-wordpress' ); ?></h2>
20
 
21
+ <h2 class="nav-tab-wrapper" id="ga-tabs">
22
+ <a class="nav-tab active" id="extensions-tab" href="#top#extensions"><?php _e( 'Extensions', 'google-analytics-for-wordpress' ); ?></a>
23
+ <a class="nav-tab" id="licenses-tab" href="#top#licenses"><?php _e( 'Licenses', 'google-analytics-for-wordpress' ); ?></a>
24
+ </h2>
25
+ <div class="tabwrapper">
26
+ <div id="extensions" class="wpseotab gatab">
27
+ <?php
28
+ foreach ( $extensions as $name => $extension ) {
29
+ if ( 'uninstalled' !== $extension->status ) {
30
+ $has_extensions = true;
31
+ }
32
+ ?>
33
+ <div class="extension <?php echo $name; ?>">
34
+ <a target="_blank" href="<?php echo $extension->url; ?>#utm_medium=banner&utm_source=gawp-config&utm_campaign=extension-page-banners">
35
+ <h3><?php echo $extension->title; ?></h3>
36
+ </a>
37
+
38
+ <p><?php echo $extension->desc; ?></p>
39
+
40
+ <p>
41
+ <?php if ( 'uninstalled' == $extension->status ) { ?>
42
+ <a target="_blank" href="https://yoast.com/wordpress/plugins/ga-ecommerce-edd/#utm_medium=banner&utm_source=gawp-config&utm_campaign=extension-page-banners" class="button-primary">Get this extension</a>
43
+ <?php } else if ( 'inactive' == $extension->status ) { ?>
44
+ <a href="#top#licenses" class="activate-link button-primary">Activate License</a>
45
+ <?php } else { ?>
46
+ <button class="button-primary installed">Installed</button>
47
+ <?php } ?>
48
+ </p>
49
+ </div>
50
+ <?php
51
+ }
52
+ ?>
53
+ </div>
54
+ <div id="licenses" class="wpseotab gatab">
55
+ <?php
56
+ if ( ! $has_extensions ) {
57
+ echo '<p>' . __( 'You have not installed any extensions for Yoast Google Analytics, so there are no licenses to activate.', 'google-analytics-for-wordpress' ) . '</p>';
58
+ } else {
59
+ do_action( 'yst_ga_show_license_form' );
60
+ }
61
+ ?>
62
  </div>
63
  </div>
64
  <div class="clear"></div>
65
+
66
  <?php
67
  echo $yoast_ga_admin->content_footer();
68
  ?>
admin/pages/settings.php CHANGED
@@ -40,7 +40,7 @@ echo $yoast_ga_admin->create_form( 'settings' );
40
  echo '</div>';
41
  echo '<div class="ga-form ga-form-input">';
42
  echo '<label class="ga-form ga-form-text-label ga-form-label-left" id="yoast-ga-form-label-text-ga-authwithgoogle" />' . __( 'Current UA-profile', 'google-analytics-for-wordpress' ) . '</label>';
43
- echo $yoast_ga_admin->get_setting( 'analytics_profile' );
44
  echo '</div>';
45
  } else {
46
  echo $yoast_ga_admin->select( 'Analytics profile', 'analytics_profile', $profiles );
@@ -50,7 +50,7 @@ echo $yoast_ga_admin->create_form( 'settings' );
50
  echo '<a class="button" href="' . $ga_url . '">' . __( 'Re-authenticate with your Google account', 'google-analytics-for-wordpress' ) . '</a>';
51
  echo '</div>';
52
  }
53
- echo "</div>";
54
 
55
  echo '<label class="ga-form ga-form-checkbox-label ga-form-label-left">';
56
  echo $yoast_ga_admin->input( 'checkbox', null, 'manual_ua_code', __( 'Manually enter your UA code', 'google-analytics-for-wordpress' ) );
@@ -65,7 +65,7 @@ echo $yoast_ga_admin->create_form( 'settings' );
65
  echo $yoast_ga_admin->input( 'checkbox', __( 'Track outbound click & downloads', 'google-analytics-for-wordpress' ), 'track_outbound', null, __( 'Clicks &amp; downloads will be tracked as events, you can find these under Content &raquo; Event Tracking in your Google Analytics reports.', 'google-analytics-for-wordpress' ) );
66
  echo $yoast_ga_admin->input( 'checkbox', __( 'Allow tracking of anonymous data', 'google-analytics-for-wordpress' ), 'anonymous_data', null, __( 'By allowing us to track anonymous data we can better help you, because we know with which WordPress configurations, themes and plugins we should test. No personal data will be submitted.', 'google-analytics-for-wordpress' ) );
67
  echo $yoast_ga_admin->input( 'checkbox', __( 'Anonymize IP\'s', 'google-analytics-for-wordpress' ), 'anonymize_ips', null, __( 'This adds <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp" target="_blank">_anonymizeIp</a></code>, 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.', 'google-analytics-for-wordpress' ) );
68
- echo $yoast_ga_admin->select( 'Ignore users', 'ignore_users', $yoast_ga_admin->get_userroles(), __( 'Hint: Select multiple roles by using CTRL or CMD.', 'google-analytics-for-wordpress' ) . '<br />' . __( 'Users of the role you select and higher will be ignored, so if you select Editor, all Editors and Administrators will be ignored.', 'google-analytics-for-wordpress' ), true );
69
  ?>
70
  </div>
71
  <div id="universal" class="gatab">
@@ -84,7 +84,7 @@ echo $yoast_ga_admin->create_form( 'settings' );
84
  echo $yoast_ga_admin->input( 'text', __( 'Subdomain tracking', 'google-analytics-for-wordpress' ), 'subdomain_tracking', null, __( 'This allows you to set the domain that\'s set by <code>setDomainName</code> for tracking subdomains, if empty this will not be set.', 'google-analytics-for-wordpress' ) );
85
 
86
  echo $yoast_ga_admin->input( 'text', __( 'Set path for internal links to track as outbound links', 'google-analytics-for-wordpress' ), 'track_internal_as_outbound', null, 'If you want to track all internal links that begin with <code>/out/</code>, enter <code>/out/</code> in the box above. If you have multiple prefixes you can separate them with comma\'s: <code>/out/,/recommends/</code>' );
87
- echo $yoast_ga_admin->input( 'text', __( 'Label for those links', 'google-analytics-for-wordpress' ), 'track_internal_as_label', null, "The label to use for these links, this will be added to where the click came from, so if the label is \"aff\", the label for a click from the content of an article becomes \"outbound-article-aff\"." );
88
 
89
  echo $yoast_ga_admin->input( 'checkbox', __( 'Tag links in RSS feed with campaign variables', 'google-analytics-for-wordpress' ), 'tag_links_in_rss', null, __( 'Do not use this feature if you use FeedBurner, as FeedBurner can do this automatically, and better than this plugin can. Check <a href="http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;answer=165769" target="_blank">this help page</a> for info on how to enable this feature in FeedBurner.', 'google-analytics-for-wordpress' ) );
90
  echo $yoast_ga_admin->input( 'checkbox', __( 'Allow anchor', 'google-analytics-for-wordpress' ), 'allow_anchor', null, __( 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking.html#_gat.GA_Tracker_._setAllowAnchor" target="_blank">_setAllowAnchor</a></code> call to your tracking code, and makes RSS link tagging use a # as well.', 'google-analytics-for-wordpress' ) );
40
  echo '</div>';
41
  echo '<div class="ga-form ga-form-input">';
42
  echo '<label class="ga-form ga-form-text-label ga-form-label-left" id="yoast-ga-form-label-text-ga-authwithgoogle" />' . __( 'Current UA-profile', 'google-analytics-for-wordpress' ) . '</label>';
43
+ echo $yoast_ga_admin->get_tracking_code();
44
  echo '</div>';
45
  } else {
46
  echo $yoast_ga_admin->select( 'Analytics profile', 'analytics_profile', $profiles );
50
  echo '<a class="button" href="' . $ga_url . '">' . __( 'Re-authenticate with your Google account', 'google-analytics-for-wordpress' ) . '</a>';
51
  echo '</div>';
52
  }
53
+ echo '</div>';
54
 
55
  echo '<label class="ga-form ga-form-checkbox-label ga-form-label-left">';
56
  echo $yoast_ga_admin->input( 'checkbox', null, 'manual_ua_code', __( 'Manually enter your UA code', 'google-analytics-for-wordpress' ) );
65
  echo $yoast_ga_admin->input( 'checkbox', __( 'Track outbound click & downloads', 'google-analytics-for-wordpress' ), 'track_outbound', null, __( 'Clicks &amp; downloads will be tracked as events, you can find these under Content &raquo; Event Tracking in your Google Analytics reports.', 'google-analytics-for-wordpress' ) );
66
  echo $yoast_ga_admin->input( 'checkbox', __( 'Allow tracking of anonymous data', 'google-analytics-for-wordpress' ), 'anonymous_data', null, __( 'By allowing us to track anonymous data we can better help you, because we know with which WordPress configurations, themes and plugins we should test. No personal data will be submitted.', 'google-analytics-for-wordpress' ) );
67
  echo $yoast_ga_admin->input( 'checkbox', __( 'Anonymize IP\'s', 'google-analytics-for-wordpress' ), 'anonymize_ips', null, __( 'This adds <code><a href="http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp" target="_blank">_anonymizeIp</a></code>, 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.', 'google-analytics-for-wordpress' ) );
68
+ echo $yoast_ga_admin->select( 'Ignore users', 'ignore_users', $yoast_ga_admin->get_userroles(), __( 'Users of the role you select will be ignored, so if you select Editor, all Editors will be ignored.', 'google-analytics-for-wordpress' ), true );
69
  ?>
70
  </div>
71
  <div id="universal" class="gatab">
84
  echo $yoast_ga_admin->input( 'text', __( 'Subdomain tracking', 'google-analytics-for-wordpress' ), 'subdomain_tracking', null, __( 'This allows you to set the domain that\'s set by <code>setDomainName</code> for tracking subdomains, if empty this will not be set.', 'google-analytics-for-wordpress' ) );
85
 
86
  echo $yoast_ga_admin->input( 'text', __( 'Set path for internal links to track as outbound links', 'google-analytics-for-wordpress' ), 'track_internal_as_outbound', null, 'If you want to track all internal links that begin with <code>/out/</code>, enter <code>/out/</code> in the box above. If you have multiple prefixes you can separate them with comma\'s: <code>/out/,/recommends/</code>' );
87
+ echo $yoast_ga_admin->input( 'text', __( 'Label for those links', 'google-analytics-for-wordpress' ), 'track_internal_as_label', null, 'The label to use for these links, this will be added to where the click came from, so if the label is "aff", the label for a click from the content of an article becomes "outbound-article-aff".' );
88
 
89
  echo $yoast_ga_admin->input( 'checkbox', __( 'Tag links in RSS feed with campaign variables', 'google-analytics-for-wordpress' ), 'tag_links_in_rss', null, __( 'Do not use this feature if you use FeedBurner, as FeedBurner can do this automatically, and better than this plugin can. Check <a href="http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;answer=165769" target="_blank">this help page</a> for info on how to enable this feature in FeedBurner.', 'google-analytics-for-wordpress' ) );
90
  echo $yoast_ga_admin->input( 'checkbox', __( 'Allow anchor', 'google-analytics-for-wordpress' ), 'allow_anchor', null, __( 'This adds a <code><a href="http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking.html#_gat.GA_Tracker_._setAllowAnchor" target="_blank">_setAllowAnchor</a></code> call to your tracking code, and makes RSS link tagging use a # as well.', 'google-analytics-for-wordpress' ) );
admin/views/{content_footer.php → content-footer.php} RENAMED
File without changes
admin/wp-gdata/OAuth.php CHANGED
@@ -3,53 +3,54 @@
3
 
4
  /* Generic exception class
5
  */
 
6
  class Yoast_OAuthException extends Exception {
7
- // pass
8
  }
9
 
10
  class Yoast_OAuthConsumer {
11
- public $key;
12
- public $secret;
13
-
14
- function __construct($key, $secret, $callback_url=NULL) {
15
- $this->key = $key;
16
- $this->secret = $secret;
17
- $this->callback_url = $callback_url;
18
- }
19
-
20
- function __toString() {
21
- return "Yoast_OAuthConsumer[key=$this->key,secret=$this->secret]";
22
- }
23
  }
24
 
25
  class Yoast_OAuthToken {
26
- // access tokens and request tokens
27
- public $key;
28
- public $secret;
29
-
30
- /**
31
- * key = the token
32
- * secret = the token secret
33
- */
34
- function __construct($key, $secret) {
35
- $this->key = $key;
36
- $this->secret = $secret;
37
- }
38
-
39
- /**
40
- * generates the basic string serialization of a token that a server
41
- * would respond to request_token and access_token calls with
42
- */
43
- function to_string() {
44
- return "oauth_token=" .
45
- Yoast_OAuthUtil::urlencode_rfc3986($this->key) .
46
- "&oauth_token_secret=" .
47
- Yoast_OAuthUtil::urlencode_rfc3986($this->secret);
48
- }
49
-
50
- function __toString() {
51
- return $this->to_string();
52
- }
53
  }
54
 
55
  /**
@@ -57,839 +58,871 @@ class Yoast_OAuthToken {
57
  * See section 9 ("Signing Requests") in the spec
58
  */
59
  abstract class Yoast_OAuthSignatureMethod {
60
- /**
61
- * Needs to return the name of the Signature Method (ie HMAC-SHA1)
62
- * @return string
63
- */
64
- abstract public function get_name();
65
-
66
- /**
67
- * Build up the signature
68
- * NOTE: The output of this function MUST NOT be urlencoded.
69
- * the encoding is handled in Yoast_OAuthRequest when the final
70
- * request is serialized
71
- * @param Yoast_OAuthRequest $request
72
- * @param Yoast_OAuthConsumer $consumer
73
- * @param Yoast_OAuthToken $token
74
- * @return string
75
- */
76
- abstract public function build_signature($request, $consumer, $token);
77
-
78
- /**
79
- * Verifies that a given signature is correct
80
- * @param Yoast_OAuthRequest $request
81
- * @param Yoast_OAuthConsumer $consumer
82
- * @param Yoast_OAuthToken $token
83
- * @param string $signature
84
- * @return bool
85
- */
86
- public function check_signature($request, $consumer, $token, $signature) {
87
- $built = $this->build_signature($request, $consumer, $token);
88
-
89
- // Check for zero length, although unlikely here
90
- if (strlen($built) == 0 || strlen($signature) == 0) {
91
- return false;
92
- }
93
-
94
- if (strlen($built) != strlen($signature)) {
95
- return false;
96
- }
97
-
98
- // Avoid a timing leak with a (hopefully) time insensitive compare
99
- $result = 0;
100
- for ($i = 0; $i < strlen($signature); $i++) {
101
- $result |= ord($built{$i}) ^ ord($signature{$i});
102
- }
103
-
104
- return $result == 0;
105
- }
 
 
 
 
106
  }
107
 
108
  /**
109
- * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
110
- * where the Signature Base String is the text and the key is the concatenated values (each first
111
- * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
112
  * character (ASCII code 38) even if empty.
113
  * - Chapter 9.2 ("HMAC-SHA1")
114
  */
115
  class Yoast_OAuthSignatureMethod_HMAC_SHA1 extends Yoast_OAuthSignatureMethod {
116
- function get_name() {
117
- return "HMAC-SHA1";
118
- }
119
 
120
- public function build_signature($request, $consumer, $token) {
121
- $base_string = $request->get_signature_base_string();
122
- $request->base_string = $base_string;
123
 
124
- $key_parts = array(
125
- $consumer->secret,
126
- ($token) ? $token->secret : ""
127
- );
128
 
129
- $key_parts = Yoast_OAuthUtil::urlencode_rfc3986($key_parts);
130
- $key = implode('&', $key_parts);
131
 
132
- return base64_encode(hash_hmac('sha1', $base_string, $key, true));
133
- }
134
  }
135
 
136
  /**
137
- * The PLAINTEXT method does not provide any security protection and SHOULD only be used
138
  * over a secure channel such as HTTPS. It does not use the Signature Base String.
139
  * - Chapter 9.4 ("PLAINTEXT")
140
  */
141
  class Yoast_OAuthSignatureMethod_PLAINTEXT extends Yoast_OAuthSignatureMethod {
142
- public function get_name() {
143
- return "PLAINTEXT";
144
- }
145
-
146
- /**
147
- * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
148
- * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
149
- * empty. The result MUST be encoded again.
150
- * - Chapter 9.4.1 ("Generating Signatures")
151
- *
152
- * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
153
- * Yoast_OAuthRequest handles this!
154
- */
155
- public function build_signature($request, $consumer, $token) {
156
- $key_parts = array(
157
- $consumer->secret,
158
- ($token) ? $token->secret : ""
159
- );
160
-
161
- $key_parts = Yoast_OAuthUtil::urlencode_rfc3986($key_parts);
162
- $key = implode('&', $key_parts);
163
- $request->base_string = $key;
164
-
165
- return $key;
166
- }
167
  }
168
 
169
  /**
170
- * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
171
- * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
172
- * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
173
- * verified way to the Service Provider, in a manner which is beyond the scope of this
174
  * specification.
175
  * - Chapter 9.3 ("RSA-SHA1")
176
  */
177
  abstract class Yoast_OAuthSignatureMethod_RSA_SHA1 extends Yoast_OAuthSignatureMethod {
178
- public function get_name() {
179
- return "RSA-SHA1";
180
- }
181
 
182
- // Up to the SP to implement this lookup of keys. Possible ideas are:
183
- // (1) do a lookup in a table of trusted certs keyed off of consumer
184
- // (2) fetch via http using a url provided by the requester
185
- // (3) some sort of specific discovery code based on request
186
- //
187
- // Either way should return a string representation of the certificate
188
- protected abstract function fetch_public_cert(&$request);
189
 
190
- // Up to the SP to implement this lookup of keys. Possible ideas are:
191
- // (1) do a lookup in a table of trusted certs keyed off of consumer
192
- //
193
- // Either way should return a string representation of the certificate
194
- protected abstract function fetch_private_cert(&$request);
195
 
196
- public function build_signature($request, $consumer, $token) {
197
- $base_string = $request->get_signature_base_string();
198
- $request->base_string = $base_string;
199
 
200
- // Fetch the private key cert based on the request
201
- $cert = $this->fetch_private_cert($request);
202
 
203
- // Pull the private key ID from the certificate
204
- $privatekeyid = openssl_get_privatekey($cert);
205
 
206
- // Sign using the key
207
- $ok = openssl_sign($base_string, $signature, $privatekeyid);
208
 
209
- // Release the key resource
210
- openssl_free_key($privatekeyid);
211
 
212
- return base64_encode($signature);
213
- }
214
 
215
- public function check_signature($request, $consumer, $token, $signature) {
216
- $decoded_sig = base64_decode($signature);
217
 
218
- $base_string = $request->get_signature_base_string();
219
 
220
- // Fetch the public key cert based on the request
221
- $cert = $this->fetch_public_cert($request);
222
 
223
- // Pull the public key ID from the certificate
224
- $publickeyid = openssl_get_publickey($cert);
225
 
226
- // Check the computed signature against the one passed in the query
227
- $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
228
 
229
- // Release the key resource
230
- openssl_free_key($publickeyid);
231
 
232
- return $ok == 1;
233
- }
234
  }
235
 
236
  class Yoast_OAuthRequest {
237
- protected $parameters;
238
- protected $http_method;
239
- protected $http_url;
240
- // for debug purposes
241
- public $base_string;
242
- public static $version = '1.0';
243
- public static $POST_INPUT = 'php://input';
244
-
245
- function __construct($http_method, $http_url, $parameters=NULL) {
246
- $parameters = ($parameters) ? $parameters : array();
247
- $parameters = array_merge( Yoast_OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters);
248
- $this->parameters = $parameters;
249
- $this->http_method = $http_method;
250
- $this->http_url = $http_url;
251
- }
252
-
253
-
254
- /**
255
- * attempt to build up a request from what was passed to the server
256
- */
257
- public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {
258
- $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on")
259
- ? 'http'
260
- : 'https';
261
- $http_url = ($http_url) ? $http_url : $scheme .
262
- '://' . $_SERVER['SERVER_NAME'] .
263
- ':' .
264
- $_SERVER['SERVER_PORT'] .
265
- $_SERVER['REQUEST_URI'];
266
- $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD'];
267
-
268
- // We weren't handed any parameters, so let's find the ones relevant to
269
- // this request.
270
- // If you run XML-RPC or similar you should use this to provide your own
271
- // parsed parameter-list
272
- if (!$parameters) {
273
- // Find request headers
274
- $request_headers = Yoast_OAuthUtil::get_headers();
275
-
276
- // Parse the query-string to find GET parameters
277
- $parameters = Yoast_OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']);
278
-
279
- // It's a POST request of the proper content-type, so parse POST
280
- // parameters and add those overriding any duplicates from GET
281
- if ($http_method == "POST"
282
- && isset($request_headers['Content-Type'])
283
- && strstr($request_headers['Content-Type'],
284
- 'application/x-www-form-urlencoded')
285
- ) {
286
- $post_data = Yoast_OAuthUtil::parse_parameters(
287
- file_get_contents(self::$POST_INPUT)
288
- );
289
- $parameters = array_merge($parameters, $post_data);
290
- }
291
-
292
- // We have a Authorization-header with OAuth data. Parse the header
293
- // and add those overriding any duplicates from GET or POST
294
- if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') {
295
- $header_parameters = Yoast_OAuthUtil::split_header(
296
- $request_headers['Authorization']
297
- );
298
- $parameters = array_merge($parameters, $header_parameters);
299
- }
300
-
301
- }
302
-
303
- return new Yoast_OAuthRequest($http_method, $http_url, $parameters);
304
- }
305
-
306
- /**
307
- * pretty much a helper function to set up the request
308
- */
309
- public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {
310
- $parameters = ($parameters) ? $parameters : array();
311
- $defaults = array("oauth_version" => Yoast_OAuthRequest::$version,
312
- "oauth_nonce" => Yoast_OAuthRequest::generate_nonce(),
313
- "oauth_timestamp" => Yoast_OAuthRequest::generate_timestamp(),
314
- "oauth_consumer_key" => $consumer->key);
315
- if ($token)
316
- $defaults['oauth_token'] = $token->key;
317
-
318
- $parameters = array_merge($defaults, $parameters);
319
-
320
- return new Yoast_OAuthRequest($http_method, $http_url, $parameters);
321
- }
322
-
323
- public function set_parameter($name, $value, $allow_duplicates = true) {
324
- if ($allow_duplicates && isset($this->parameters[$name])) {
325
- // We have already added parameter(s) with this name, so add to the list
326
- if (is_scalar($this->parameters[$name])) {
327
- // This is the first duplicate, so transform scalar (string)
328
- // into an array so we can add the duplicates
329
- $this->parameters[$name] = array($this->parameters[$name]);
330
- }
331
-
332
- $this->parameters[$name][] = $value;
333
- } else {
334
- $this->parameters[$name] = $value;
335
- }
336
- }
337
-
338
- public function get_parameter($name) {
339
- return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
340
- }
341
-
342
- public function get_parameters() {
343
- return $this->parameters;
344
- }
345
-
346
- public function unset_parameter($name) {
347
- unset($this->parameters[$name]);
348
- }
349
-
350
- /**
351
- * The request parameters, sorted and concatenated into a normalized string.
352
- * @return string
353
- */
354
- public function get_signable_parameters() {
355
- // Grab all parameters
356
- $params = $this->parameters;
357
-
358
- // Remove oauth_signature if present
359
- // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
360
- if (isset($params['oauth_signature'])) {
361
- unset($params['oauth_signature']);
362
- }
363
-
364
- return Yoast_OAuthUtil::build_http_query($params);
365
- }
366
-
367
- /**
368
- * Returns the base string of this request
369
- *
370
- * The base string defined as the method, the url
371
- * and the parameters (normalized), each urlencoded
372
- * and the concated with &.
373
- */
374
- public function get_signature_base_string() {
375
- $parts = array(
376
- $this->get_normalized_http_method(),
377
- $this->get_normalized_http_url(),
378
- $this->get_signable_parameters()
379
- );
380
-
381
- $parts = Yoast_OAuthUtil::urlencode_rfc3986($parts);
382
-
383
- return implode('&', $parts);
384
- }
385
-
386
- /**
387
- * just uppercases the http method
388
- */
389
- public function get_normalized_http_method() {
390
- return strtoupper($this->http_method);
391
- }
392
-
393
- /**
394
- * parses the url and rebuilds it to be
395
- * scheme://host/path
396
- */
397
- public function get_normalized_http_url() {
398
- $parts = parse_url($this->http_url);
399
-
400
- $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
401
- $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
402
- $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
403
- $path = (isset($parts['path'])) ? $parts['path'] : '';
404
-
405
- if (($scheme == 'https' && $port != '443')
406
- || ($scheme == 'http' && $port != '80')) {
407
- $host = "$host:$port";
408
- }
409
- return "$scheme://$host$path";
410
- }
411
-
412
- /**
413
- * builds a url usable for a GET request
414
- */
415
- public function to_url() {
416
- $post_data = $this->to_postdata();
417
- $out = $this->get_normalized_http_url();
418
- if ($post_data) {
419
- $out .= '?'.$post_data;
420
- }
421
- return $out;
422
- }
423
-
424
- /**
425
- * builds the data one would send in a POST request
426
- */
427
- public function to_postdata() {
428
- return Yoast_OAuthUtil::build_http_query($this->parameters);
429
- }
430
-
431
- /**
432
- * builds the Authorization: header
433
- */
434
- public function to_header($realm=null) {
435
- $first = true;
436
- if($realm) {
437
- $out = 'Authorization: OAuth realm="' . Yoast_OAuthUtil::urlencode_rfc3986($realm) . '"';
438
- $first = false;
439
- } else
440
- $out = 'Authorization: OAuth';
441
-
442
- $total = array();
443
- foreach ($this->parameters as $k => $v) {
444
- if (substr($k, 0, 5) != "oauth") continue;
445
- if (is_array($v)) {
446
- throw new Yoast_OAuthException('Arrays not supported in headers');
447
- }
448
- $out .= ($first) ? ' ' : ',';
449
- $out .= Yoast_OAuthUtil::urlencode_rfc3986($k) .
450
- '="' .
451
- Yoast_OAuthUtil::urlencode_rfc3986($v) .
452
- '"';
453
- $first = false;
454
- }
455
- return $out;
456
- }
457
-
458
- public function __toString() {
459
- return $this->to_url();
460
- }
461
-
462
-
463
- public function sign_request($signature_method, $consumer, $token) {
464
- $this->set_parameter(
465
- "oauth_signature_method",
466
- $signature_method->get_name(),
467
- false
468
- );
469
- $signature = $this->build_signature($signature_method, $consumer, $token);
470
- $this->set_parameter("oauth_signature", $signature, false);
471
- }
472
-
473
- public function build_signature($signature_method, $consumer, $token) {
474
- $signature = $signature_method->build_signature($this, $consumer, $token);
475
- return $signature;
476
- }
477
-
478
- /**
479
- * util function: current timestamp
480
- */
481
- private static function generate_timestamp() {
482
- return time();
483
- }
484
-
485
- /**
486
- * util function: current nonce
487
- */
488
- private static function generate_nonce() {
489
- $mt = microtime();
490
- $rand = mt_rand();
491
-
492
- return md5($mt . $rand); // md5s look nicer than numbers
493
- }
 
 
 
 
 
 
 
 
 
 
494
  }
495
 
496
  class Yoast_OAuthServer {
497
- protected $timestamp_threshold = 300; // in seconds, five minutes
498
- protected $version = '1.0'; // hi blaine
499
- protected $signature_methods = array();
500
-
501
- protected $data_store;
502
-
503
- function __construct($data_store) {
504
- $this->data_store = $data_store;
505
- }
506
-
507
- public function add_signature_method($signature_method) {
508
- $this->signature_methods[$signature_method->get_name()] =
509
- $signature_method;
510
- }
511
-
512
- // high level functions
513
-
514
- /**
515
- * process a request_token request
516
- * returns the request token on success
517
- */
518
- public function fetch_request_token(&$request) {
519
- $this->get_version($request);
520
-
521
- $consumer = $this->get_consumer($request);
522
-
523
- // no token required for the initial token request
524
- $token = NULL;
525
-
526
- $this->check_signature($request, $consumer, $token);
527
-
528
- // Rev A change
529
- $callback = $request->get_parameter('oauth_callback');
530
- $new_token = $this->data_store->new_request_token($consumer, $callback);
531
-
532
- return $new_token;
533
- }
534
-
535
- /**
536
- * process an access_token request
537
- * returns the access token on success
538
- */
539
- public function fetch_access_token(&$request) {
540
- $this->get_version($request);
541
-
542
- $consumer = $this->get_consumer($request);
543
-
544
- // requires authorized request token
545
- $token = $this->get_token($request, $consumer, "request");
546
-
547
- $this->check_signature($request, $consumer, $token);
548
-
549
- // Rev A change
550
- $verifier = $request->get_parameter('oauth_verifier');
551
- $new_token = $this->data_store->new_access_token($token, $consumer, $verifier);
552
-
553
- return $new_token;
554
- }
555
-
556
- /**
557
- * verify an api call, checks all the parameters
558
- */
559
- public function verify_request(&$request) {
560
- $this->get_version($request);
561
- $consumer = $this->get_consumer($request);
562
- $token = $this->get_token($request, $consumer, "access");
563
- $this->check_signature($request, $consumer, $token);
564
- return array($consumer, $token);
565
- }
566
-
567
- // Internals from here
568
- /**
569
- * version 1
570
- */
571
- private function get_version(&$request) {
572
- $version = $request->get_parameter("oauth_version");
573
- if (!$version) {
574
- // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.
575
- // Chapter 7.0 ("Accessing Protected Ressources")
576
- $version = '1.0';
577
- }
578
- if ($version !== $this->version) {
579
- throw new Yoast_OAuthException("OAuth version '$version' not supported");
580
- }
581
- return $version;
582
- }
583
-
584
- /**
585
- * figure out the signature with some defaults
586
- */
587
- private function get_signature_method($request) {
588
- $signature_method = $request instanceof Yoast_OAuthRequest
589
- ? $request->get_parameter("oauth_signature_method")
590
- : NULL;
591
-
592
- if (!$signature_method) {
593
- // According to chapter 7 ("Accessing Protected Ressources") the signature-method
594
- // parameter is required, and we can't just fallback to PLAINTEXT
595
- throw new Yoast_OAuthException('No signature method parameter. This parameter is required');
596
- }
597
-
598
- if (!in_array($signature_method,
599
- array_keys($this->signature_methods))) {
600
- throw new Yoast_OAuthException(
601
- "Signature method '$signature_method' not supported " .
602
- "try one of the following: " .
603
- implode(", ", array_keys($this->signature_methods))
604
- );
605
- }
606
- return $this->signature_methods[$signature_method];
607
- }
608
-
609
- /**
610
- * try to find the consumer for the provided request's consumer key
611
- */
612
- private function get_consumer($request) {
613
- $consumer_key = $request instanceof Yoast_OAuthRequest
614
- ? $request->get_parameter("oauth_consumer_key")
615
- : NULL;
616
-
617
- if (!$consumer_key) {
618
- throw new Yoast_OAuthException("Invalid consumer key");
619
- }
620
-
621
- $consumer = $this->data_store->lookup_consumer($consumer_key);
622
- if (!$consumer) {
623
- throw new Yoast_OAuthException("Invalid consumer");
624
- }
625
-
626
- return $consumer;
627
- }
628
-
629
- /**
630
- * try to find the token for the provided request's token key
631
- */
632
- private function get_token($request, $consumer, $token_type="access") {
633
- $token_field = $request instanceof Yoast_OAuthRequest
634
- ? $request->get_parameter('oauth_token')
635
- : NULL;
636
-
637
- $token = $this->data_store->lookup_token(
638
- $consumer, $token_type, $token_field
639
- );
640
- if (!$token) {
641
- throw new Yoast_OAuthException("Invalid $token_type token: $token_field");
642
- }
643
- return $token;
644
- }
645
-
646
- /**
647
- * all-in-one function to check the signature on a request
648
- * should guess the signature method appropriately
649
- */
650
- private function check_signature($request, $consumer, $token) {
651
- // this should probably be in a different method
652
- $timestamp = $request instanceof Yoast_OAuthRequest
653
- ? $request->get_parameter('oauth_timestamp')
654
- : NULL;
655
- $nonce = $request instanceof Yoast_OAuthRequest
656
- ? $request->get_parameter('oauth_nonce')
657
- : NULL;
658
-
659
- $this->check_timestamp($timestamp);
660
- $this->check_nonce($consumer, $token, $nonce, $timestamp);
661
-
662
- $signature_method = $this->get_signature_method($request);
663
-
664
- $signature = $request->get_parameter('oauth_signature');
665
- $valid_sig = $signature_method->check_signature(
666
- $request,
667
- $consumer,
668
- $token,
669
- $signature
670
- );
671
-
672
- if (!$valid_sig) {
673
- throw new Yoast_OAuthException("Invalid signature");
674
- }
675
- }
676
-
677
- /**
678
- * check that the timestamp is new enough
679
- */
680
- private function check_timestamp($timestamp) {
681
- if( ! $timestamp )
682
- throw new Yoast_OAuthException(
683
- 'Missing timestamp parameter. The parameter is required'
684
- );
685
-
686
- // verify that timestamp is recentish
687
- $now = time();
688
- if (abs($now - $timestamp) > $this->timestamp_threshold) {
689
- throw new Yoast_OAuthException(
690
- "Expired timestamp, yours $timestamp, ours $now"
691
- );
692
- }
693
- }
694
-
695
- /**
696
- * check that the nonce is not repeated
697
- */
698
- private function check_nonce($consumer, $token, $nonce, $timestamp) {
699
- if( ! $nonce )
700
- throw new Yoast_OAuthException(
701
- 'Missing nonce parameter. The parameter is required'
702
- );
703
-
704
- // verify that the nonce is uniqueish
705
- $found = $this->data_store->lookup_nonce(
706
- $consumer,
707
- $token,
708
- $nonce,
709
- $timestamp
710
- );
711
- if ($found) {
712
- throw new Yoast_OAuthException("Nonce already used: $nonce");
713
- }
714
- }
 
 
 
 
 
 
 
715
 
716
  }
717
 
718
  class Yoast_OAuthDataStore {
719
- function lookup_consumer($consumer_key) {
720
- // implement me
721
- }
722
 
723
- function lookup_token($consumer, $token_type, $token) {
724
- // implement me
725
- }
726
 
727
- function lookup_nonce($consumer, $token, $nonce, $timestamp) {
728
- // implement me
729
- }
730
 
731
- function new_request_token($consumer, $callback = null) {
732
- // return a new token attached to this consumer
733
- }
734
 
735
- function new_access_token($token, $consumer, $verifier = null) {
736
- // return a new access token attached to this consumer
737
- // for the user associated with this token if the request token
738
- // is authorized
739
- // should also invalidate the request token
740
- }
741
 
742
  }
743
 
744
  class Yoast_OAuthUtil {
745
- public static function urlencode_rfc3986($input) {
746
- if (is_array($input)) {
747
- return array_map(array('Yoast_OAuthUtil', 'urlencode_rfc3986'), $input);
748
- } else if (is_scalar($input)) {
749
- return str_replace(
750
- '+',
751
- ' ',
752
- str_replace('%7E', '~', rawurlencode($input))
753
- );
754
- } else {
755
- return '';
756
- }
757
- }
758
-
759
-
760
- // This decode function isn't taking into consideration the above
761
- // modifications to the encoding process. However, this method doesn't
762
- // seem to be used anywhere so leaving it as is.
763
- public static function urldecode_rfc3986($string) {
764
- return urldecode($string);
765
- }
766
-
767
- // Utility function for turning the Authorization: header into
768
- // parameters, has to do some unescaping
769
- // Can filter out any non-oauth parameters if needed (default behaviour)
770
- // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
771
- // see http://code.google.com/p/oauth/issues/detail?id=163
772
- public static function split_header($header, $only_allow_oauth_parameters = true) {
773
- $params = array();
774
- if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) {
775
- foreach ($matches[1] as $i => $h) {
776
- $params[$h] = Yoast_OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]);
777
- }
778
- if (isset($params['realm'])) {
779
- unset($params['realm']);
780
- }
781
- }
782
- return $params;
783
- }
784
-
785
- // helper to try to sort out headers for people who aren't running apache
786
- public static function get_headers() {
787
- if (function_exists('apache_request_headers')) {
788
- // we need this to get the actual Authorization: header
789
- // because apache tends to tell us it doesn't exist
790
- $headers = apache_request_headers();
791
-
792
- // sanitize the output of apache_request_headers because
793
- // we always want the keys to be Cased-Like-This and arh()
794
- // returns the headers in the same case as they are in the
795
- // request
796
- $out = array();
797
- foreach ($headers AS $key => $value) {
798
- $key = str_replace(
799
- " ",
800
- "-",
801
- ucwords(strtolower(str_replace("-", " ", $key)))
802
- );
803
- $out[$key] = $value;
804
- }
805
- } else {
806
- // otherwise we don't have apache and are just going to have to hope
807
- // that $_SERVER actually contains what we need
808
- $out = array();
809
- if( isset($_SERVER['CONTENT_TYPE']) )
810
- $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
811
- if( isset($_ENV['CONTENT_TYPE']) )
812
- $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
813
-
814
- foreach ($_SERVER as $key => $value) {
815
- if (substr($key, 0, 5) == "HTTP_") {
816
- // this is chaos, basically it is just there to capitalize the first
817
- // letter of every word that is not an initial HTTP and strip HTTP
818
- // code from przemek
819
- $key = str_replace(
820
- " ",
821
- "-",
822
- ucwords(strtolower(str_replace("_", " ", substr($key, 5))))
823
- );
824
- $out[$key] = $value;
825
- }
826
- }
827
- }
828
- return $out;
829
- }
830
-
831
- // This function takes a input like a=b&a=c&d=e and returns the parsed
832
- // parameters like this
833
- // array('a' => array('b','c'), 'd' => 'e')
834
- public static function parse_parameters( $input ) {
835
- if (!isset($input) || !$input) return array();
836
-
837
- $pairs = explode('&', $input);
838
-
839
- $parsed_parameters = array();
840
- foreach ($pairs as $pair) {
841
- $split = explode('=', $pair, 2);
842
- $parameter = Yoast_OAuthUtil::urldecode_rfc3986($split[0]);
843
- $value = isset($split[1]) ? Yoast_OAuthUtil::urldecode_rfc3986($split[1]) : '';
844
-
845
- if (isset($parsed_parameters[$parameter])) {
846
- // We have already recieved parameter(s) with this name, so add to the list
847
- // of parameters with this name
848
-
849
- if (is_scalar($parsed_parameters[$parameter])) {
850
- // This is the first duplicate, so transform scalar (string) into an array
851
- // so we can add the duplicates
852
- $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
853
- }
854
-
855
- $parsed_parameters[$parameter][] = $value;
856
- } else {
857
- $parsed_parameters[$parameter] = $value;
858
- }
859
- }
860
- return $parsed_parameters;
861
- }
862
-
863
- public static function build_http_query($params) {
864
- if (!$params) return '';
865
-
866
- // Urlencode both keys and values
867
- $keys = Yoast_OAuthUtil::urlencode_rfc3986(array_keys($params));
868
- $values = Yoast_OAuthUtil::urlencode_rfc3986(array_values($params));
869
- $params = array_combine($keys, $values);
870
-
871
- // Parameters are sorted by name, using lexicographical byte value ordering.
872
- // Ref: Spec: 9.1.1 (1)
873
- uksort($params, 'strcmp');
874
-
875
- $pairs = array();
876
- foreach ($params as $parameter => $value) {
877
- if (is_array($value)) {
878
- // If two or more parameters share the same name, they are sorted by their value
879
- // Ref: Spec: 9.1.1 (1)
880
- // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
881
- sort($value, SORT_STRING);
882
- foreach ($value as $duplicate_value) {
883
- $pairs[] = $parameter . '=' . $duplicate_value;
884
- }
885
- } else {
886
- $pairs[] = $parameter . '=' . $value;
887
- }
888
- }
889
- // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
890
- // Each name-value pair is separated by an '&' character (ASCII code 38)
891
- return implode('&', $pairs);
892
- }
 
 
 
 
 
 
 
 
 
 
 
893
  }
894
 
895
  ?>
3
 
4
  /* Generic exception class
5
  */
6
+
7
  class Yoast_OAuthException extends Exception {
8
+ // pass
9
  }
10
 
11
  class Yoast_OAuthConsumer {
12
+ public $key;
13
+ public $secret;
14
+
15
+ function __construct( $key, $secret, $callback_url = null ) {
16
+ $this->key = $key;
17
+ $this->secret = $secret;
18
+ $this->callback_url = $callback_url;
19
+ }
20
+
21
+ function __toString() {
22
+ return "Yoast_OAuthConsumer[key=$this->key,secret=$this->secret]";
23
+ }
24
  }
25
 
26
  class Yoast_OAuthToken {
27
+ // access tokens and request tokens
28
+ public $key;
29
+ public $secret;
30
+
31
+ /**
32
+ * key = the token
33
+ * secret = the token secret
34
+ */
35
+ function __construct( $key, $secret ) {
36
+ $this->key = $key;
37
+ $this->secret = $secret;
38
+ }
39
+
40
+ /**
41
+ * generates the basic string serialization of a token that a server
42
+ * would respond to request_token and access_token calls with
43
+ */
44
+ function to_string() {
45
+ return 'oauth_token=' .
46
+ Yoast_OAuthUtil::urlencode_rfc3986( $this->key ) .
47
+ '&oauth_token_secret=' .
48
+ Yoast_OAuthUtil::urlencode_rfc3986( $this->secret );
49
+ }
50
+
51
+ function __toString() {
52
+ return $this->to_string();
53
+ }
54
  }
55
 
56
  /**
58
  * See section 9 ("Signing Requests") in the spec
59
  */
60
  abstract class Yoast_OAuthSignatureMethod {
61
+ /**
62
+ * Needs to return the name of the Signature Method (ie HMAC-SHA1)
63
+ * @return string
64
+ */
65
+ abstract public function get_name();
66
+
67
+ /**
68
+ * Build up the signature
69
+ * NOTE: The output of this function MUST NOT be urlencoded.
70
+ * the encoding is handled in Yoast_OAuthRequest when the final
71
+ * request is serialized
72
+ *
73
+ * @param Yoast_OAuthRequest $request
74
+ * @param Yoast_OAuthConsumer $consumer
75
+ * @param Yoast_OAuthToken $token
76
+ *
77
+ * @return string
78
+ */
79
+ abstract public function build_signature( $request, $consumer, $token );
80
+
81
+ /**
82
+ * Verifies that a given signature is correct
83
+ *
84
+ * @param Yoast_OAuthRequest $request
85
+ * @param Yoast_OAuthConsumer $consumer
86
+ * @param Yoast_OAuthToken $token
87
+ * @param string $signature
88
+ *
89
+ * @return bool
90
+ */
91
+ public function check_signature( $request, $consumer, $token, $signature ) {
92
+ $built = $this->build_signature( $request, $consumer, $token );
93
+
94
+ // Check for zero length, although unlikely here
95
+ if ( strlen( $built ) == 0 || strlen( $signature ) == 0 ) {
96
+ return false;
97
+ }
98
+
99
+ if ( strlen( $built ) != strlen( $signature ) ) {
100
+ return false;
101
+ }
102
+
103
+ // Avoid a timing leak with a (hopefully) time insensitive compare
104
+ $result = 0;
105
+ for ( $i = 0; $i < strlen( $signature ); $i ++ ) {
106
+ $result |= ord( $built{$i} ) ^ ord( $signature{$i} );
107
+ }
108
+
109
+ return $result == 0;
110
+ }
111
  }
112
 
113
  /**
114
+ * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
115
+ * where the Signature Base String is the text and the key is the concatenated values (each first
116
+ * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
117
  * character (ASCII code 38) even if empty.
118
  * - Chapter 9.2 ("HMAC-SHA1")
119
  */
120
  class Yoast_OAuthSignatureMethod_HMAC_SHA1 extends Yoast_OAuthSignatureMethod {
121
+ function get_name() {
122
+ return 'HMAC-SHA1';
123
+ }
124
 
125
+ public function build_signature( $request, $consumer, $token ) {
126
+ $base_string = $request->get_signature_base_string();
127
+ $request->base_string = $base_string;
128
 
129
+ $key_parts = array(
130
+ $consumer->secret,
131
+ ( $token ) ? $token->secret : '',
132
+ );
133
 
134
+ $key_parts = Yoast_OAuthUtil::urlencode_rfc3986( $key_parts );
135
+ $key = implode( '&', $key_parts );
136
 
137
+ return base64_encode( hash_hmac( 'sha1', $base_string, $key, true ) );
138
+ }
139
  }
140
 
141
  /**
142
+ * The PLAINTEXT method does not provide any security protection and SHOULD only be used
143
  * over a secure channel such as HTTPS. It does not use the Signature Base String.
144
  * - Chapter 9.4 ("PLAINTEXT")
145
  */
146
  class Yoast_OAuthSignatureMethod_PLAINTEXT extends Yoast_OAuthSignatureMethod {
147
+ public function get_name() {
148
+ return 'PLAINTEXT';
149
+ }
150
+
151
+ /**
152
+ * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
153
+ * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
154
+ * empty. The result MUST be encoded again.
155
+ * - Chapter 9.4.1 ("Generating Signatures")
156
+ *
157
+ * Please note that the second encoding MUST NOT happen in the SignatureMethod, as
158
+ * Yoast_OAuthRequest handles this!
159
+ */
160
+ public function build_signature( $request, $consumer, $token ) {
161
+ $key_parts = array(
162
+ $consumer->secret,
163
+ ( $token ) ? $token->secret : '',
164
+ );
165
+
166
+ $key_parts = Yoast_OAuthUtil::urlencode_rfc3986( $key_parts );
167
+ $key = implode( '&', $key_parts );
168
+ $request->base_string = $key;
169
+
170
+ return $key;
171
+ }
172
  }
173
 
174
  /**
175
+ * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
176
+ * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
177
+ * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
178
+ * verified way to the Service Provider, in a manner which is beyond the scope of this
179
  * specification.
180
  * - Chapter 9.3 ("RSA-SHA1")
181
  */
182
  abstract class Yoast_OAuthSignatureMethod_RSA_SHA1 extends Yoast_OAuthSignatureMethod {
183
+ public function get_name() {
184
+ return 'RSA-SHA1';
185
+ }
186
 
187
+ // Up to the SP to implement this lookup of keys. Possible ideas are:
188
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
189
+ // (2) fetch via http using a url provided by the requester
190
+ // (3) some sort of specific discovery code based on request
191
+ //
192
+ // Either way should return a string representation of the certificate
193
+ protected abstract function fetch_public_cert( &$request );
194
 
195
+ // Up to the SP to implement this lookup of keys. Possible ideas are:
196
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
197
+ //
198
+ // Either way should return a string representation of the certificate
199
+ protected abstract function fetch_private_cert( &$request );
200
 
201
+ public function build_signature( $request, $consumer, $token ) {
202
+ $base_string = $request->get_signature_base_string();
203
+ $request->base_string = $base_string;
204
 
205
+ // Fetch the private key cert based on the request
206
+ $cert = $this->fetch_private_cert( $request );
207
 
208
+ // Pull the private key ID from the certificate
209
+ $privatekeyid = openssl_get_privatekey( $cert );
210
 
211
+ // Sign using the key
212
+ $ok = openssl_sign( $base_string, $signature, $privatekeyid );
213
 
214
+ // Release the key resource
215
+ openssl_free_key( $privatekeyid );
216
 
217
+ return base64_encode( $signature );
218
+ }
219
 
220
+ public function check_signature( $request, $consumer, $token, $signature ) {
221
+ $decoded_sig = base64_decode( $signature );
222
 
223
+ $base_string = $request->get_signature_base_string();
224
 
225
+ // Fetch the public key cert based on the request
226
+ $cert = $this->fetch_public_cert( $request );
227
 
228
+ // Pull the public key ID from the certificate
229
+ $publickeyid = openssl_get_publickey( $cert );
230
 
231
+ // Check the computed signature against the one passed in the query
232
+ $ok = openssl_verify( $base_string, $decoded_sig, $publickeyid );
233
 
234
+ // Release the key resource
235
+ openssl_free_key( $publickeyid );
236
 
237
+ return $ok == 1;
238
+ }
239
  }
240
 
241
  class Yoast_OAuthRequest {
242
+ protected $parameters;
243
+ protected $http_method;
244
+ protected $http_url;
245
+ // for debug purposes
246
+ public $base_string;
247
+ public static $version = '1.0';
248
+ public static $POST_INPUT = 'php://input';
249
+
250
+ function __construct( $http_method, $http_url, $parameters = null ) {
251
+ $parameters = ( $parameters ) ? $parameters : array();
252
+ $parameters = array_merge( Yoast_OAuthUtil::parse_parameters( parse_url( $http_url, PHP_URL_QUERY ) ), $parameters );
253
+ $this->parameters = $parameters;
254
+ $this->http_method = $http_method;
255
+ $this->http_url = $http_url;
256
+ }
257
+
258
+
259
+ /**
260
+ * attempt to build up a request from what was passed to the server
261
+ */
262
+ public static function from_request( $http_method = null, $http_url = null, $parameters = null ) {
263
+ $scheme = ( ! isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS'] != 'on' )
264
+ ? 'http'
265
+ : 'https';
266
+ $http_url = ( $http_url ) ? $http_url : $scheme .
267
+ '://' . $_SERVER['SERVER_NAME'] .
268
+ ':' .
269
+ $_SERVER['SERVER_PORT'] .
270
+ $_SERVER['REQUEST_URI'];
271
+ $http_method = ( $http_method ) ? $http_method : $_SERVER['REQUEST_METHOD'];
272
+
273
+ // We weren't handed any parameters, so let's find the ones relevant to
274
+ // this request.
275
+ // If you run XML-RPC or similar you should use this to provide your own
276
+ // parsed parameter-list
277
+ if ( ! $parameters ) {
278
+ // Find request headers
279
+ $request_headers = Yoast_OAuthUtil::get_headers();
280
+
281
+ // Parse the query-string to find GET parameters
282
+ $parameters = Yoast_OAuthUtil::parse_parameters( $_SERVER['QUERY_STRING'] );
283
+
284
+ // It's a POST request of the proper content-type, so parse POST
285
+ // parameters and add those overriding any duplicates from GET
286
+ if ( $http_method == 'POST'
287
+ && isset( $request_headers['Content-Type'] )
288
+ && strstr( $request_headers['Content-Type'],
289
+ 'application/x-www-form-urlencoded' )
290
+ ) {
291
+ $post_data = Yoast_OAuthUtil::parse_parameters(
292
+ file_get_contents( self::$POST_INPUT )
293
+ );
294
+ $parameters = array_merge( $parameters, $post_data );
295
+ }
296
+
297
+ // We have a Authorization-header with OAuth data. Parse the header
298
+ // and add those overriding any duplicates from GET or POST
299
+ if ( isset( $request_headers['Authorization'] ) && substr( $request_headers['Authorization'], 0, 6 ) == 'OAuth ' ) {
300
+ $header_parameters = Yoast_OAuthUtil::split_header(
301
+ $request_headers['Authorization']
302
+ );
303
+ $parameters = array_merge( $parameters, $header_parameters );
304
+ }
305
+ }
306
+
307
+ return new Yoast_OAuthRequest( $http_method, $http_url, $parameters );
308
+ }
309
+
310
+ /**
311
+ * pretty much a helper function to set up the request
312
+ */
313
+ public static function from_consumer_and_token( $consumer, $token, $http_method, $http_url, $parameters = null ) {
314
+ $parameters = ( $parameters ) ? $parameters : array();
315
+ $defaults = array(
316
+ 'oauth_version' => Yoast_OAuthRequest::$version,
317
+ 'oauth_nonce' => Yoast_OAuthRequest::generate_nonce(),
318
+ 'oauth_timestamp' => Yoast_OAuthRequest::generate_timestamp(),
319
+ 'oauth_consumer_key' => $consumer->key,
320
+ );
321
+ if ( $token ) {
322
+ $defaults['oauth_token'] = $token->key;
323
+ }
324
+
325
+ $parameters = array_merge( $defaults, $parameters );
326
+
327
+ return new Yoast_OAuthRequest( $http_method, $http_url, $parameters );
328
+ }
329
+
330
+ public function set_parameter( $name, $value, $allow_duplicates = true ) {
331
+ if ( $allow_duplicates && isset( $this->parameters[$name] ) ) {
332
+ // We have already added parameter(s) with this name, so add to the list
333
+ if ( is_scalar( $this->parameters[$name] ) ) {
334
+ // This is the first duplicate, so transform scalar (string)
335
+ // into an array so we can add the duplicates
336
+ $this->parameters[$name] = array( $this->parameters[$name] );
337
+ }
338
+
339
+ $this->parameters[$name][] = $value;
340
+ } else {
341
+ $this->parameters[$name] = $value;
342
+ }
343
+ }
344
+
345
+ public function get_parameter( $name ) {
346
+ return isset( $this->parameters[$name] ) ? $this->parameters[$name] : null;
347
+ }
348
+
349
+ public function get_parameters() {
350
+ return $this->parameters;
351
+ }
352
+
353
+ public function unset_parameter( $name ) {
354
+ unset( $this->parameters[$name] );
355
+ }
356
+
357
+ /**
358
+ * The request parameters, sorted and concatenated into a normalized string.
359
+ * @return string
360
+ */
361
+ public function get_signable_parameters() {
362
+ // Grab all parameters
363
+ $params = $this->parameters;
364
+
365
+ // Remove oauth_signature if present
366
+ // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
367
+ if ( isset( $params['oauth_signature'] ) ) {
368
+ unset( $params['oauth_signature'] );
369
+ }
370
+
371
+ return Yoast_OAuthUtil::build_http_query( $params );
372
+ }
373
+
374
+ /**
375
+ * Returns the base string of this request
376
+ *
377
+ * The base string defined as the method, the url
378
+ * and the parameters (normalized), each urlencoded
379
+ * and the concated with &.
380
+ */
381
+ public function get_signature_base_string() {
382
+ $parts = array(
383
+ $this->get_normalized_http_method(),
384
+ $this->get_normalized_http_url(),
385
+ $this->get_signable_parameters(),
386
+ );
387
+
388
+ $parts = Yoast_OAuthUtil::urlencode_rfc3986( $parts );
389
+
390
+ return implode( '&', $parts );
391
+ }
392
+
393
+ /**
394
+ * just uppercases the http method
395
+ */
396
+ public function get_normalized_http_method() {
397
+ return strtoupper( $this->http_method );
398
+ }
399
+
400
+ /**
401
+ * parses the url and rebuilds it to be
402
+ * scheme://host/path
403
+ */
404
+ public function get_normalized_http_url() {
405
+ $parts = parse_url( $this->http_url );
406
+
407
+ $scheme = ( isset( $parts['scheme'] ) ) ? $parts['scheme'] : 'http';
408
+ $port = ( isset( $parts['port'] ) ) ? $parts['port'] : ( ( $scheme == 'https' ) ? '443' : '80' );
409
+ $host = ( isset( $parts['host'] ) ) ? strtolower( $parts['host'] ) : '';
410
+ $path = ( isset( $parts['path'] ) ) ? $parts['path'] : '';
411
+
412
+ if ( ( $scheme == 'https' && $port != '443' )
413
+ || ( $scheme == 'http' && $port != '80' )
414
+ ) {
415
+ $host = "$host:$port";
416
+ }
417
+
418
+ return "$scheme://$host$path";
419
+ }
420
+
421
+ /**
422
+ * builds a url usable for a GET request
423
+ */
424
+ public function to_url() {
425
+ $post_data = $this->to_postdata();
426
+ $out = $this->get_normalized_http_url();
427
+ if ( $post_data ) {
428
+ $out .= '?' . $post_data;
429
+ }
430
+
431
+ return $out;
432
+ }
433
+
434
+ /**
435
+ * builds the data one would send in a POST request
436
+ */
437
+ public function to_postdata() {
438
+ return Yoast_OAuthUtil::build_http_query( $this->parameters );
439
+ }
440
+
441
+ /**
442
+ * builds the Authorization: header
443
+ */
444
+ public function to_header( $realm = null ) {
445
+ $first = true;
446
+ if ( $realm ) {
447
+ $out = 'Authorization: OAuth realm="' . Yoast_OAuthUtil::urlencode_rfc3986( $realm ) . '"';
448
+ $first = false;
449
+ } else {
450
+ $out = 'Authorization: OAuth';
451
+ }
452
+
453
+ $total = array();
454
+ foreach ( $this->parameters as $k => $v ) {
455
+ if ( substr( $k, 0, 5 ) != 'oauth' ) {
456
+ continue;
457
+ }
458
+ if ( is_array( $v ) ) {
459
+ throw new Yoast_OAuthException( 'Arrays not supported in headers' );
460
+ }
461
+ $out .= ( $first ) ? ' ' : ',';
462
+ $out .= Yoast_OAuthUtil::urlencode_rfc3986( $k ) .
463
+ '="' .
464
+ Yoast_OAuthUtil::urlencode_rfc3986( $v ) .
465
+ '"';
466
+ $first = false;
467
+ }
468
+
469
+ return $out;
470
+ }
471
+
472
+ public function __toString() {
473
+ return $this->to_url();
474
+ }
475
+
476
+
477
+ public function sign_request( $signature_method, $consumer, $token ) {
478
+ $this->set_parameter(
479
+ 'oauth_signature_method',
480
+ $signature_method->get_name(),
481
+ false
482
+ );
483
+ $signature = $this->build_signature( $signature_method, $consumer, $token );
484
+ $this->set_parameter( 'oauth_signature', $signature, false );
485
+ }
486
+
487
+ public function build_signature( $signature_method, $consumer, $token ) {
488
+ $signature = $signature_method->build_signature( $this, $consumer, $token );
489
+
490
+ return $signature;
491
+ }
492
+
493
+ /**
494
+ * util function: current timestamp
495
+ */
496
+ private static function generate_timestamp() {
497
+ return time();
498
+ }
499
+
500
+ /**
501
+ * util function: current nonce
502
+ */
503
+ private static function generate_nonce() {
504
+ $mt = microtime();
505
+ $rand = mt_rand();
506
+
507
+ return md5( $mt . $rand ); // md5s look nicer than numbers
508
+ }
509
  }
510
 
511
  class Yoast_OAuthServer {
512
+ protected $timestamp_threshold = 300; // in seconds, five minutes
513
+ protected $version = '1.0'; // hi blaine
514
+ protected $signature_methods = array();
515
+
516
+ protected $data_store;
517
+
518
+ function __construct( $data_store ) {
519
+ $this->data_store = $data_store;
520
+ }
521
+
522
+ public function add_signature_method( $signature_method ) {
523
+ $this->signature_methods[$signature_method->get_name()] =
524
+ $signature_method;
525
+ }
526
+
527
+ // high level functions
528
+
529
+ /**
530
+ * process a request_token request
531
+ * returns the request token on success
532
+ */
533
+ public function fetch_request_token( &$request ) {
534
+ $this->get_version( $request );
535
+
536
+ $consumer = $this->get_consumer( $request );
537
+
538
+ // no token required for the initial token request
539
+ $token = null;
540
+
541
+ $this->check_signature( $request, $consumer, $token );
542
+
543
+ // Rev A change
544
+ $callback = $request->get_parameter( 'oauth_callback' );
545
+ $new_token = $this->data_store->new_request_token( $consumer, $callback );
546
+
547
+ return $new_token;
548
+ }
549
+
550
+ /**
551
+ * process an access_token request
552
+ * returns the access token on success
553
+ */
554
+ public function fetch_access_token( &$request ) {
555
+ $this->get_version( $request );
556
+
557
+ $consumer = $this->get_consumer( $request );
558
+
559
+ // requires authorized request token
560
+ $token = $this->get_token( $request, $consumer, 'request' );
561
+
562
+ $this->check_signature( $request, $consumer, $token );
563
+
564
+ // Rev A change
565
+ $verifier = $request->get_parameter( 'oauth_verifier' );
566
+ $new_token = $this->data_store->new_access_token( $token, $consumer, $verifier );
567
+
568
+ return $new_token;
569
+ }
570
+
571
+ /**
572
+ * verify an api call, checks all the parameters
573
+ */
574
+ public function verify_request( &$request ) {
575
+ $this->get_version( $request );
576
+ $consumer = $this->get_consumer( $request );
577
+ $token = $this->get_token( $request, $consumer, 'access' );
578
+ $this->check_signature( $request, $consumer, $token );
579
+
580
+ return array( $consumer, $token );
581
+ }
582
+
583
+ // Internals from here
584
+ /**
585
+ * version 1
586
+ */
587
+ private function get_version( &$request ) {
588
+ $version = $request->get_parameter( 'oauth_version' );
589
+ if ( ! $version ) {
590
+ // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present.
591
+ // Chapter 7.0 ("Accessing Protected Ressources")
592
+ $version = '1.0';
593
+ }
594
+ if ( $version !== $this->version ) {
595
+ throw new Yoast_OAuthException( 'OAuth version ' . $version . ' not supported' );
596
+ }
597
+
598
+ return $version;
599
+ }
600
+
601
+ /**
602
+ * figure out the signature with some defaults
603
+ */
604
+ private function get_signature_method( $request ) {
605
+ $signature_method = $request instanceof Yoast_OAuthRequest
606
+ ? $request->get_parameter( 'oauth_signature_method' )
607
+ : null;
608
+
609
+ if ( ! $signature_method ) {
610
+ // According to chapter 7 ("Accessing Protected Ressources") the signature-method
611
+ // parameter is required, and we can't just fallback to PLAINTEXT
612
+ throw new Yoast_OAuthException( 'No signature method parameter. This parameter is required' );
613
+ }
614
+
615
+ if ( ! in_array( $signature_method,
616
+ array_keys( $this->signature_methods ) )
617
+ ) {
618
+ throw new Yoast_OAuthException(
619
+ 'Signature method ' . $signature_method . ' not supported ' .
620
+ 'try one of the following: ' .
621
+ implode( ', ', array_keys( $this->signature_methods ) )
622
+ );
623
+ }
624
+
625
+ return $this->signature_methods[$signature_method];
626
+ }
627
+
628
+ /**
629
+ * try to find the consumer for the provided request's consumer key
630
+ */
631
+ private function get_consumer( $request ) {
632
+ $consumer_key = $request instanceof Yoast_OAuthRequest
633
+ ? $request->get_parameter( 'oauth_consumer_key' )
634
+ : null;
635
+
636
+ if ( ! $consumer_key ) {
637
+ throw new Yoast_OAuthException( 'Invalid consumer key' );
638
+ }
639
+
640
+ $consumer = $this->data_store->lookup_consumer( $consumer_key );
641
+ if ( ! $consumer ) {
642
+ throw new Yoast_OAuthException( 'Invalid consumer' );
643
+ }
644
+
645
+ return $consumer;
646
+ }
647
+
648
+ /**
649
+ * try to find the token for the provided request's token key
650
+ */
651
+ private function get_token( $request, $consumer, $token_type = 'access' ) {
652
+ $token_field = $request instanceof Yoast_OAuthRequest
653
+ ? $request->get_parameter( 'oauth_token' )
654
+ : null;
655
+
656
+ $token = $this->data_store->lookup_token(
657
+ $consumer, $token_type, $token_field
658
+ );
659
+ if ( ! $token ) {
660
+ throw new Yoast_OAuthException( "Invalid $token_type token: $token_field" );
661
+ }
662
+
663
+ return $token;
664
+ }
665
+
666
+ /**
667
+ * all-in-one function to check the signature on a request
668
+ * should guess the signature method appropriately
669
+ */
670
+ private function check_signature( $request, $consumer, $token ) {
671
+ // this should probably be in a different method
672
+ $timestamp = $request instanceof Yoast_OAuthRequest
673
+ ? $request->get_parameter( 'oauth_timestamp' )
674
+ : null;
675
+ $nonce = $request instanceof Yoast_OAuthRequest
676
+ ? $request->get_parameter( 'oauth_nonce' )
677
+ : null;
678
+
679
+ $this->check_timestamp( $timestamp );
680
+ $this->check_nonce( $consumer, $token, $nonce, $timestamp );
681
+
682
+ $signature_method = $this->get_signature_method( $request );
683
+
684
+ $signature = $request->get_parameter( 'oauth_signature' );
685
+ $valid_sig = $signature_method->check_signature(
686
+ $request,
687
+ $consumer,
688
+ $token,
689
+ $signature
690
+ );
691
+
692
+ if ( ! $valid_sig ) {
693
+ throw new Yoast_OAuthException( 'Invalid signature' );
694
+ }
695
+ }
696
+
697
+ /**
698
+ * check that the timestamp is new enough
699
+ */
700
+ private function check_timestamp( $timestamp ) {
701
+ if ( ! $timestamp ) {
702
+ throw new Yoast_OAuthException(
703
+ 'Missing timestamp parameter. The parameter is required'
704
+ );
705
+ }
706
+
707
+ // verify that timestamp is recentish
708
+ $now = time();
709
+ if ( abs( $now - $timestamp ) > $this->timestamp_threshold ) {
710
+ throw new Yoast_OAuthException(
711
+ "Expired timestamp, yours $timestamp, ours $now"
712
+ );
713
+ }
714
+ }
715
+
716
+ /**
717
+ * check that the nonce is not repeated
718
+ */
719
+ private function check_nonce( $consumer, $token, $nonce, $timestamp ) {
720
+ if ( ! $nonce ) {
721
+ throw new Yoast_OAuthException(
722
+ 'Missing nonce parameter. The parameter is required'
723
+ );
724
+ }
725
+
726
+ // verify that the nonce is uniqueish
727
+ $found = $this->data_store->lookup_nonce(
728
+ $consumer,
729
+ $token,
730
+ $nonce,
731
+ $timestamp
732
+ );
733
+ if ( $found ) {
734
+ throw new Yoast_OAuthException( "Nonce already used: $nonce" );
735
+ }
736
+ }
737
 
738
  }
739
 
740
  class Yoast_OAuthDataStore {
741
+ function lookup_consumer( $consumer_key ) {
742
+ // implement me
743
+ }
744
 
745
+ function lookup_token( $consumer, $token_type, $token ) {
746
+ // implement me
747
+ }
748
 
749
+ function lookup_nonce( $consumer, $token, $nonce, $timestamp ) {
750
+ // implement me
751
+ }
752
 
753
+ function new_request_token( $consumer, $callback = null ) {
754
+ // return a new token attached to this consumer
755
+ }
756
 
757
+ function new_access_token( $token, $consumer, $verifier = null ) {
758
+ // return a new access token attached to this consumer
759
+ // for the user associated with this token if the request token
760
+ // is authorized
761
+ // should also invalidate the request token
762
+ }
763
 
764
  }
765
 
766
  class Yoast_OAuthUtil {
767
+ public static function urlencode_rfc3986( $input ) {
768
+ if ( is_array( $input ) ) {
769
+ return array_map( array( 'Yoast_OAuthUtil', 'urlencode_rfc3986' ), $input );
770
+ } else {
771
+ if ( is_scalar( $input ) ) {
772
+ return str_replace(
773
+ '+',
774
+ ' ',
775
+ str_replace( '%7E', '~', rawurlencode( $input ) )
776
+ );
777
+ } else {
778
+ return '';
779
+ }
780
+ }
781
+ }
782
+
783
+
784
+ // This decode function isn't taking into consideration the above
785
+ // modifications to the encoding process. However, this method doesn't
786
+ // seem to be used anywhere so leaving it as is.
787
+ public static function urldecode_rfc3986( $string ) {
788
+ return urldecode( $string );
789
+ }
790
+
791
+ // Utility function for turning the Authorization: header into
792
+ // parameters, has to do some unescaping
793
+ // Can filter out any non-oauth parameters if needed (default behaviour)
794
+ // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement.
795
+ // see http://code.google.com/p/oauth/issues/detail?id=163
796
+ public static function split_header( $header, $only_allow_oauth_parameters = true ) {
797
+ $params = array();
798
+ if ( preg_match_all( '/(' . ( $only_allow_oauth_parameters ? 'oauth_' : '' ) . '[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches ) ) {
799
+ foreach ( $matches[1] as $i => $h ) {
800
+ $params[$h] = Yoast_OAuthUtil::urldecode_rfc3986( empty( $matches[3][$i] ) ? $matches[4][$i] : $matches[3][$i] );
801
+ }
802
+ if ( isset( $params['realm'] ) ) {
803
+ unset( $params['realm'] );
804
+ }
805
+ }
806
+
807
+ return $params;
808
+ }
809
+
810
+ // helper to try to sort out headers for people who aren't running apache
811
+ public static function get_headers() {
812
+ if ( function_exists( 'apache_request_headers' ) ) {
813
+ // we need this to get the actual Authorization: header
814
+ // because apache tends to tell us it doesn't exist
815
+ $headers = apache_request_headers();
816
+
817
+ // sanitize the output of apache_request_headers because
818
+ // we always want the keys to be Cased-Like-This and arh()
819
+ // returns the headers in the same case as they are in the
820
+ // request
821
+ $out = array();
822
+ foreach ( $headers AS $key => $value ) {
823
+ $key = str_replace(
824
+ ' ',
825
+ '-',
826
+ ucwords( strtolower( str_replace( '-', ' ', $key ) ) )
827
+ );
828
+ $out[$key] = $value;
829
+ }
830
+ } else {
831
+ // otherwise we don't have apache and are just going to have to hope
832
+ // that $_SERVER actually contains what we need
833
+ $out = array();
834
+ if ( isset( $_SERVER['CONTENT_TYPE'] ) ) {
835
+ $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
836
+ }
837
+ if ( isset( $_ENV['CONTENT_TYPE'] ) ) {
838
+ $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
839
+ }
840
+
841
+ foreach ( $_SERVER as $key => $value ) {
842
+ if ( substr( $key, 0, 5 ) == 'HTTP_' ) {
843
+ // this is chaos, basically it is just there to capitalize the first
844
+ // letter of every word that is not an initial HTTP and strip HTTP
845
+ // code from przemek
846
+ $key = str_replace(
847
+ ' ',
848
+ '-',
849
+ ucwords( strtolower( str_replace( '_', ' ', substr( $key, 5 ) ) ) )
850
+ );
851
+ $out[$key] = $value;
852
+ }
853
+ }
854
+ }
855
+
856
+ return $out;
857
+ }
858
+
859
+ // This function takes a input like a=b&a=c&d=e and returns the parsed
860
+ // parameters like this
861
+ // array('a' => array('b','c'), 'd' => 'e')
862
+ public static function parse_parameters( $input ) {
863
+ if ( ! isset( $input ) || ! $input ) {
864
+ return array();
865
+ }
866
+
867
+ $pairs = explode( '&', $input );
868
+
869
+ $parsed_parameters = array();
870
+ foreach ( $pairs as $pair ) {
871
+ $split = explode( '=', $pair, 2 );
872
+ $parameter = Yoast_OAuthUtil::urldecode_rfc3986( $split[0] );
873
+ $value = isset( $split[1] ) ? Yoast_OAuthUtil::urldecode_rfc3986( $split[1] ) : '';
874
+
875
+ if ( isset( $parsed_parameters[$parameter] ) ) {
876
+ // We have already recieved parameter(s) with this name, so add to the list
877
+ // of parameters with this name
878
+
879
+ if ( is_scalar( $parsed_parameters[$parameter] ) ) {
880
+ // This is the first duplicate, so transform scalar (string) into an array
881
+ // so we can add the duplicates
882
+ $parsed_parameters[$parameter] = array( $parsed_parameters[$parameter] );
883
+ }
884
+
885
+ $parsed_parameters[$parameter][] = $value;
886
+ } else {
887
+ $parsed_parameters[$parameter] = $value;
888
+ }
889
+ }
890
+
891
+ return $parsed_parameters;
892
+ }
893
+
894
+ public static function build_http_query( $params ) {
895
+ if ( ! $params ) {
896
+ return '';
897
+ }
898
+
899
+ // Urlencode both keys and values
900
+ $keys = Yoast_OAuthUtil::urlencode_rfc3986( array_keys( $params ) );
901
+ $values = Yoast_OAuthUtil::urlencode_rfc3986( array_values( $params ) );
902
+ $params = array_combine( $keys, $values );
903
+
904
+ // Parameters are sorted by name, using lexicographical byte value ordering.
905
+ // Ref: Spec: 9.1.1 (1)
906
+ uksort( $params, 'strcmp' );
907
+
908
+ $pairs = array();
909
+ foreach ( $params as $parameter => $value ) {
910
+ if ( is_array( $value ) ) {
911
+ // If two or more parameters share the same name, they are sorted by their value
912
+ // Ref: Spec: 9.1.1 (1)
913
+ // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
914
+ sort( $value, SORT_STRING );
915
+ foreach ( $value as $duplicate_value ) {
916
+ $pairs[] = $parameter . '=' . $duplicate_value;
917
+ }
918
+ } else {
919
+ $pairs[] = $parameter . '=' . $value;
920
+ }
921
+ }
922
+ // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
923
+ // Each name-value pair is separated by an '&' character (ASCII code 38)
924
+ return implode( '&', $pairs );
925
+ }
926
  }
927
 
928
  ?>
admin/wp-gdata/wp-gdata.php CHANGED
@@ -6,8 +6,9 @@
6
  */
7
 
8
  // Load the OAuth library.
9
- if ( ! class_exists( 'Yoast_OAuthConsumer' ) )
10
  require( 'OAuth.php' );
 
11
 
12
  class WP_GData {
13
  /* Contains the last HTTP status code returned. */
@@ -18,24 +19,27 @@ class WP_GData {
18
  const access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken';
19
 
20
  function __construct( $parameters = array(), $oauth_token = null, $oauth_token_secret = null ) {
21
- $this->parameters = $parameters;
22
  $this->signature_method = new Yoast_OAuthSignatureMethod_HMAC_SHA1();
23
- $this->consumer = new Yoast_OAuthConsumer( 'anonymous', 'anonymous' );
24
 
25
- if ( !empty( $oauth_token ) && !empty( $oauth_token_secret ) )
26
  $this->token = new Yoast_OAuthConsumer( $oauth_token, $oauth_token_secret );
27
- else
28
  $this->token = null;
 
29
  }
30
 
31
  function get_request_token( $oauth_callback = null ) {
32
  $parameters = $this->parameters;
33
- if ( !empty( $oauth_callback ) )
34
  $parameters['oauth_callback'] = $oauth_callback;
 
35
 
36
- $request = $this->oauth_request( self::request_token_url, 'GET', $parameters );
37
- $token = Yoast_OAuthUtil::parse_parameters( wp_remote_retrieve_body( $request ) );
38
  $this->token = new Yoast_OAuthConsumer( $token['oauth_token'], $token['oauth_token_secret'] );
 
39
  return $token;
40
  }
41
 
@@ -46,15 +50,17 @@ class WP_GData {
46
  $request = Yoast_OAuthRequest::from_consumer_and_token( $this->consumer, $this->token, $method, $url, $parameters );
47
  $request->sign_request( $this->signature_method, $this->consumer, $this->token );
48
 
49
- if ( 'GET' == $method )
50
  return wp_remote_get( $request->to_url() );
51
- else
52
  return wp_remote_post( $request->to_url(), $request->to_postdata() );
53
- }
 
54
 
55
  function get_authorize_url( $token ) {
56
- if ( is_array( $token ) )
57
  $token = $token['oauth_token'];
 
58
 
59
  return self::authorize_url . "?oauth_token={$token}";
60
  }
@@ -68,38 +74,40 @@ class WP_GData {
68
  */
69
  function get_access_token( $oauth_verifier = '' ) {
70
  $parameters = array();
71
- if ( !empty( $oauth_verifier ) )
72
  $parameters['oauth_verifier'] = $oauth_verifier;
 
73
 
74
- $request = $this->oauth_request( self::access_token_url, 'GET', $parameters );
75
- $token = Yoast_OAuthUtil::parse_parameters( wp_remote_retrieve_body( $request ) );
76
  $this->token = new Yoast_OAuthConsumer( $token['oauth_token'], $token['oauth_token_secret'] );
 
77
  return $token;
78
  }
79
 
80
  /**
81
- * GET wrapper for oAuthRequest.
82
- */
83
  public function get( $url, $parameters = array() ) {
84
  return $this->oauth_request( $url, 'GET', $parameters );
85
  }
86
 
87
  /**
88
- * POST wrapper for oAuthRequest.
89
- */
90
  public function post( $url, $parameters = array() ) {
91
- $defaults = array(
92
- 'method' => 'POST',
93
- 'timeout' => 30,
94
  'redirection' => 5,
95
  'httpversion' => '1.0',
96
- 'blocking' => true,
97
- 'body' => array(),
98
- 'headers' => array(),
99
- 'cookies' => array()
100
  );
101
  $parameters = array_merge( $defaults, $parameters );
102
 
103
  return $this->oauth_request( $url, 'POST', $parameters );
104
- }
105
  }
6
  */
7
 
8
  // Load the OAuth library.
9
+ if ( ! class_exists( 'Yoast_OAuthConsumer' ) ) {
10
  require( 'OAuth.php' );
11
+ }
12
 
13
  class WP_GData {
14
  /* Contains the last HTTP status code returned. */
19
  const access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken';
20
 
21
  function __construct( $parameters = array(), $oauth_token = null, $oauth_token_secret = null ) {
22
+ $this->parameters = $parameters;
23
  $this->signature_method = new Yoast_OAuthSignatureMethod_HMAC_SHA1();
24
+ $this->consumer = new Yoast_OAuthConsumer( 'anonymous', 'anonymous' );
25
 
26
+ if ( ! empty( $oauth_token ) && ! empty( $oauth_token_secret ) ) {
27
  $this->token = new Yoast_OAuthConsumer( $oauth_token, $oauth_token_secret );
28
+ } else {
29
  $this->token = null;
30
+ }
31
  }
32
 
33
  function get_request_token( $oauth_callback = null ) {
34
  $parameters = $this->parameters;
35
+ if ( ! empty( $oauth_callback ) ) {
36
  $parameters['oauth_callback'] = $oauth_callback;
37
+ }
38
 
39
+ $request = $this->oauth_request( self::request_token_url, 'GET', $parameters );
40
+ $token = Yoast_OAuthUtil::parse_parameters( wp_remote_retrieve_body( $request ) );
41
  $this->token = new Yoast_OAuthConsumer( $token['oauth_token'], $token['oauth_token_secret'] );
42
+
43
  return $token;
44
  }
45
 
50
  $request = Yoast_OAuthRequest::from_consumer_and_token( $this->consumer, $this->token, $method, $url, $parameters );
51
  $request->sign_request( $this->signature_method, $this->consumer, $this->token );
52
 
53
+ if ( 'GET' == $method ) {
54
  return wp_remote_get( $request->to_url() );
55
+ } else {
56
  return wp_remote_post( $request->to_url(), $request->to_postdata() );
57
+ }
58
+ }
59
 
60
  function get_authorize_url( $token ) {
61
+ if ( is_array( $token ) ) {
62
  $token = $token['oauth_token'];
63
+ }
64
 
65
  return self::authorize_url . "?oauth_token={$token}";
66
  }
74
  */
75
  function get_access_token( $oauth_verifier = '' ) {
76
  $parameters = array();
77
+ if ( ! empty( $oauth_verifier ) ) {
78
  $parameters['oauth_verifier'] = $oauth_verifier;
79
+ }
80
 
81
+ $request = $this->oauth_request( self::access_token_url, 'GET', $parameters );
82
+ $token = Yoast_OAuthUtil::parse_parameters( wp_remote_retrieve_body( $request ) );
83
  $this->token = new Yoast_OAuthConsumer( $token['oauth_token'], $token['oauth_token_secret'] );
84
+
85
  return $token;
86
  }
87
 
88
  /**
89
+ * GET wrapper for oAuthRequest.
90
+ */
91
  public function get( $url, $parameters = array() ) {
92
  return $this->oauth_request( $url, 'GET', $parameters );
93
  }
94
 
95
  /**
96
+ * POST wrapper for oAuthRequest.
97
+ */
98
  public function post( $url, $parameters = array() ) {
99
+ $defaults = array(
100
+ 'method' => 'POST',
101
+ 'timeout' => 30,
102
  'redirection' => 5,
103
  'httpversion' => '1.0',
104
+ 'blocking' => true,
105
+ 'body' => array(),
106
+ 'headers' => array(),
107
+ 'cookies' => array()
108
  );
109
  $parameters = array_merge( $defaults, $parameters );
110
 
111
  return $this->oauth_request( $url, 'POST', $parameters );
112
+ }
113
  }
css/chosen.css ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* @group Base */
2
+ .chzn-container {
3
+ display: inline-block;
4
+ zoom: 1;
5
+ position: relative;
6
+ font-size: 13px;
7
+ *display: inline;
8
+ }
9
+
10
+ .chzn-container .chzn-drop {
11
+ position: absolute;
12
+ z-index: 1010;
13
+ top: 29px;
14
+ left: 0;
15
+ border: 1px solid #aaa;
16
+ border-top: 0;
17
+ background: #fff;
18
+ box-shadow: 0 4px 5px rgba(0,0,0,0.15);
19
+ }
20
+ /* @end */
21
+
22
+ /* @group Single Chosen */
23
+ .chzn-container-single .chzn-single {
24
+ display: block;
25
+ overflow: hidden;
26
+ position: relative;
27
+ height: 23px;
28
+ padding: 0 0 0 8px;
29
+ border: 1px solid #aaa;
30
+ border-radius: 5px;
31
+ color: #444;
32
+ background-color: #fff;
33
+ background-image: linear-gradient(#fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%);
34
+ background-clip: padding-box;
35
+ box-shadow: 0 0 3px #fff inset, 0 1px 1px rgba(0,0,0,0.1);
36
+ line-height: 24px;
37
+ white-space: nowrap;
38
+ text-decoration: none;
39
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 );
40
+ }
41
+
42
+ .chzn-container-single .chzn-default {
43
+ color: #999;
44
+ }
45
+
46
+ .chzn-container-single .chzn-single span {
47
+ display: block;
48
+ overflow: hidden;
49
+ margin-right: 26px;
50
+ white-space: nowrap;
51
+ text-overflow: ellipsis;
52
+ -ms-text-overflow: ellipsis;
53
+ -o-text-overflow: ellipsis;
54
+ }
55
+
56
+ .chzn-container-single .chzn-single abbr {
57
+ display: block;
58
+ position: absolute;
59
+ top: 6px;
60
+ right: 26px;
61
+ width: 12px;
62
+ height: 12px;
63
+ background: url("../img/chosen-sprite.png") -42px 1px no-repeat;
64
+ font-size: 1px;
65
+ }
66
+
67
+ .chzn-container-single .chzn-single abbr:hover {
68
+ background-position: -42px -10px;
69
+ }
70
+
71
+ .chzn-container-single.chzn-disabled .chzn-single abbr:hover {
72
+ background-position: -42px -10px;
73
+ }
74
+
75
+ .chzn-container-single .chzn-single div {
76
+ display: block;
77
+ position: absolute;
78
+ top: 0;
79
+ right: 0;
80
+ width: 18px;
81
+ height: 100%;
82
+ }
83
+
84
+ .chzn-container-single .chzn-single div b {
85
+ display: block;
86
+ width: 100%;
87
+ height: 100%;
88
+ background: url("../img/chosen-sprite.png") no-repeat 0 2px;
89
+ }
90
+
91
+ .chzn-container-single .chzn-search {
92
+ position: relative;
93
+ z-index: 1010;
94
+ margin: 0;
95
+ padding: 3px 4px;
96
+ white-space: nowrap;
97
+ }
98
+
99
+ .chzn-container-single .chzn-search input {
100
+ margin: 1px 0;
101
+ padding: 4px 20px 4px 5px;
102
+ border: 1px solid #aaa;
103
+ outline: 0;
104
+ background: #fff url("../img/chosen-sprite.png") no-repeat 100% -20px;
105
+ background: url("../img/chosen-sprite.png") no-repeat 100% -20px, linear-gradient(#eee 1%, #fff 15%);
106
+ font-family: sans-serif;
107
+ font-size: 1em;
108
+ }
109
+
110
+ .chzn-container-single .chzn-drop {
111
+ border-radius: 0 0 4px 4px;
112
+ background-clip: padding-box;
113
+ }
114
+ /* @end */
115
+
116
+ .chzn-container-single-nosearch .chzn-search input {
117
+ position: absolute;
118
+ left: -9000px;
119
+ }
120
+
121
+ /* @group Multi Chosen */
122
+ .chzn-container-multi .chzn-choices {
123
+ overflow: hidden;
124
+ position: relative;
125
+ height: auto !important;
126
+ height: 1%;
127
+ margin: 0;
128
+ padding: 0;
129
+ border: 1px solid #aaa;
130
+ background-color: #fff;
131
+ background-image: linear-gradient(#eee 1%, #fff 15%);
132
+ cursor: text;
133
+ }
134
+
135
+ .chzn-container-multi .chzn-choices li {
136
+ float: left;
137
+ list-style: none;
138
+ }
139
+
140
+ .chzn-container-multi .chzn-choices .search-field {
141
+ margin: 0;
142
+ padding: 0;
143
+ white-space: nowrap;
144
+ }
145
+
146
+ .chzn-container-multi .chzn-choices .search-field input {
147
+ height: 15px;
148
+ margin: 1px 0;
149
+ padding: 5px;
150
+ border: 0 !important;
151
+ outline: 0;
152
+ color: #666;
153
+ background: transparent !important;
154
+ box-shadow: none;
155
+ font-family: sans-serif;
156
+ font-size: 100%;
157
+ }
158
+
159
+ .chzn-container-multi .chzn-choices .search-field .default {
160
+ color: #999;
161
+ }
162
+
163
+ .chzn-container-multi .chzn-choices .search-choice {
164
+ position: relative;
165
+ margin: 3px 0 3px 5px;
166
+ padding: 3px 20px 3px 5px;
167
+ border: 1px solid #aaa;
168
+ border-radius: 3px;
169
+ color: #333;
170
+ background-color: #e4e4e4;
171
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
172
+ background-clip: padding-box;
173
+ box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0,0,0,0.05);
174
+ line-height: 13px;
175
+ cursor: default;
176
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
177
+ }
178
+
179
+ .chzn-container-multi .chzn-choices .search-choice.search-choice-disabled {
180
+ padding-right: 5px;
181
+ border: 1px solid #ccc;
182
+ color: #666;
183
+ background-color: #e4e4e4;
184
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
185
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
186
+ }
187
+
188
+ .chzn-container-multi .chzn-choices .search-choice-focus {
189
+ background: #d4d4d4;
190
+ }
191
+
192
+ .chzn-container-multi .chzn-choices .search-choice .search-choice-close {
193
+ display: block;
194
+ position: absolute;
195
+ top: 4px;
196
+ right: 3px;
197
+ width: 12px;
198
+ height: 12px;
199
+ background: url("../img/chosen-sprite.png") -42px 1px no-repeat;
200
+ font-size: 1px;
201
+ }
202
+
203
+ .chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover {
204
+ background-position: -42px -10px;
205
+ }
206
+
207
+ .chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close {
208
+ background-position: -42px -10px;
209
+ }
210
+ /* @end */
211
+
212
+ /* @group Results */
213
+ .chzn-container .chzn-results {
214
+ overflow-x: hidden;
215
+ overflow-y: auto;
216
+ position: relative;
217
+ max-height: 240px;
218
+ margin: 0 4px 4px 0;
219
+ padding: 0 0 0 4px;
220
+ -webkit-overflow-scrolling: touch;
221
+ }
222
+
223
+ .chzn-container-multi .chzn-results {
224
+ margin: -1px 0 0;
225
+ padding: 0;
226
+ }
227
+
228
+ .chzn-container .chzn-results li {
229
+ display: none;
230
+ margin: 0;
231
+ padding: 5px 6px;
232
+ line-height: 15px;
233
+ list-style: none;
234
+ }
235
+
236
+ .chzn-container .chzn-results .active-result {
237
+ display: list-item;
238
+ cursor: pointer;
239
+ }
240
+
241
+ .chzn-container .chzn-results .highlighted {
242
+ color: #fff;
243
+ background-color: #3875d7;
244
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
245
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0 );
246
+ }
247
+
248
+ .chzn-container .chzn-results li em {
249
+ background: #feffde;
250
+ font-style: normal;
251
+ }
252
+
253
+ .chzn-container .chzn-results .highlighted em {
254
+ background: transparent;
255
+ }
256
+
257
+ .chzn-container .chzn-results .no-results {
258
+ display: list-item;
259
+ background: #f4f4f4;
260
+ }
261
+
262
+ .chzn-container .chzn-results .group-result {
263
+ color: #999;
264
+ font-weight: bold;
265
+ cursor: default;
266
+ }
267
+
268
+ .chzn-container .chzn-results .group-option {
269
+ padding-left: 15px;
270
+ }
271
+
272
+ .chzn-container-multi .chzn-drop .result-selected {
273
+ display: none;
274
+ }
275
+
276
+ .chzn-container .chzn-results-scroll {
277
+ position: absolute;
278
+ z-index: 1;
279
+ width: 321px;
280
+ /* This should by dynamic with js */
281
+ margin: 0 4px;
282
+ background: white;
283
+ text-align: center;
284
+ }
285
+
286
+ .chzn-container .chzn-results-scroll span {
287
+ display: inline-block;
288
+ width: 9px;
289
+ height: 17px;
290
+ text-indent: -5000px;
291
+ }
292
+
293
+ .chzn-container .chzn-results-scroll-down {
294
+ bottom: 0;
295
+ }
296
+
297
+ .chzn-container .chzn-results-scroll-down span {
298
+ background: url("../img/chosen-sprite.png") no-repeat -4px -3px;
299
+ }
300
+
301
+ .chzn-container .chzn-results-scroll-up span {
302
+ background: url("../img/chosen-sprite.png") no-repeat -22px -3px;
303
+ }
304
+ /* @end */
305
+
306
+ /* @group Active */
307
+ .chzn-container-active .chzn-single {
308
+ border: 1px solid #5897fb;
309
+ box-shadow: 0 0 5px rgba(0,0,0,0.3);
310
+ }
311
+
312
+ .chzn-container-active .chzn-single-with-drop {
313
+ border: 1px solid #aaa;
314
+ border-bottom-right-radius: 0;
315
+ border-bottom-left-radius: 0;
316
+ background-color: #eee;
317
+ background-image: linear-gradient(#eee 20%, #fff 80%);
318
+ box-shadow: 0 1px 0 #fff inset;
319
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 );
320
+ }
321
+
322
+ .chzn-container-active .chzn-single-with-drop div {
323
+ border-left: none;
324
+ background: transparent;
325
+ }
326
+
327
+ .chzn-container-active .chzn-single-with-drop div b {
328
+ background-position: -18px 2px;
329
+ }
330
+
331
+ .chzn-container-active .chzn-choices {
332
+ border: 1px solid #5897fb;
333
+ box-shadow: 0 0 5px rgba(0,0,0,0.3);
334
+ }
335
+
336
+ .chzn-container-active .chzn-choices .search-field input {
337
+ color: #111 !important;
338
+ }
339
+ /* @end */
340
+
341
+ /* @group Disabled Support */
342
+ .chzn-disabled {
343
+ opacity: 0.5 !important;
344
+ cursor: default;
345
+ }
346
+
347
+ .chzn-disabled .chzn-single {
348
+ cursor: default;
349
+ }
350
+
351
+ .chzn-disabled .chzn-choices .search-choice .search-choice-close {
352
+ cursor: default;
353
+ }
354
+
355
+ /* @group Right to Left */
356
+ .chzn-rtl {
357
+ text-align: right;
358
+ }
359
+
360
+ .chzn-rtl .chzn-single {
361
+ overflow: visible;
362
+ padding: 0 8px 0 0;
363
+ }
364
+
365
+ .chzn-rtl .chzn-single span {
366
+ margin-right: 0;
367
+ margin-left: 26px;
368
+ direction: rtl;
369
+ }
370
+
371
+ .chzn-rtl .chzn-single div {
372
+ right: auto;
373
+ left: 3px;
374
+ }
375
+
376
+ .chzn-rtl .chzn-single abbr {
377
+ right: auto;
378
+ left: 26px;
379
+ }
380
+
381
+ .chzn-rtl .chzn-choices .search-field input {
382
+ direction: rtl;
383
+ }
384
+
385
+ .chzn-rtl .chzn-choices li {
386
+ float: right;
387
+ }
388
+
389
+ .chzn-rtl .chzn-choices .search-choice {
390
+ margin: 3px 5px 3px 0;
391
+ padding: 3px 5px 3px 19px;
392
+ }
393
+
394
+ .chzn-rtl .chzn-choices .search-choice .search-choice-close {
395
+ right: auto;
396
+ left: 4px;
397
+ }
398
+
399
+ .chzn-rtl.chzn-container-single .chzn-results {
400
+ margin: 0 0 4px 4px;
401
+ padding: 0 4px 0 0;
402
+ }
403
+
404
+ .chzn-rtl .chzn-results .group-option {
405
+ padding-right: 15px;
406
+ padding-left: 0;
407
+ }
408
+
409
+ .chzn-rtl.chzn-container-active .chzn-single-with-drop div {
410
+ border-right: none;
411
+ }
412
+
413
+ .chzn-rtl .chzn-search input {
414
+ padding: 4px 5px 4px 20px;
415
+ background: #fff url("../img/chosen-sprite.png") no-repeat -30px -20px;
416
+ background: url("../img/chosen-sprite.png") no-repeat -30px -20px, linear-gradient(#eee 1%, #fff 15%);
417
+ direction: rtl;
418
+ }
419
+
420
+ .chzn-container-single.chzn-rtl .chzn-single div b {
421
+ background-position: 6px 2px;
422
+ }
423
+
424
+ .chzn-container-single.chzn-rtl .chzn-single-with-drop div b {
425
+ background-position: -12px 2px;
426
+ }
427
+ /* @end */
428
+
429
+ /* @group Retina compatibility */
430
+ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
431
+ .chzn-rtl .chzn-search input, .chzn-container-single .chzn-single abbr, .chzn-container-single .chzn-single div b, .chzn-container-single .chzn-search input, .chzn-container-multi .chzn-choices .search-choice .search-choice-close, .chzn-container .chzn-results-scroll-down span, .chzn-container .chzn-results-scroll-up span {
432
+ background-image: url("../img/chosen-sprite@2x.png") !important;
433
+ background-repeat: no-repeat !important;
434
+ background-size: 52px 37px !important;
435
+ }
436
+ }
437
+ /* @end */
css/chosen.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .chzn-container{display:inline-block;zoom:1;position:relative;font-size:13px;*display:inline}.chzn-container .chzn-drop{position:absolute;z-index:1010;top:29px;left:0;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chzn-container-single .chzn-single{display:block;overflow:hidden;position:relative;height:23px;padding:0 0 0 8px;border:1px solid #aaa;border-radius:5px;color:#444;background-color:#fff;background-image:linear-gradient(#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);line-height:24px;white-space:nowrap;text-decoration:none;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0)}.chzn-container-single .chzn-default{color:#999}.chzn-container-single .chzn-single span{display:block;overflow:hidden;margin-right:26px;white-space:nowrap;text-overflow:ellipsis;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis}.chzn-container-single .chzn-single abbr{display:block;position:absolute;top:6px;right:26px;width:12px;height:12px;background:url(../img/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chzn-container-single .chzn-single abbr:hover,.chzn-container-single.chzn-disabled .chzn-single abbr:hover{background-position:-42px -10px}.chzn-container-single .chzn-single div{display:block;position:absolute;top:0;right:0;width:18px;height:100%}.chzn-container-single .chzn-single div b{display:block;width:100%;height:100%;background:url(../img/chosen-sprite.png) no-repeat 0 2px}.chzn-container-single .chzn-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chzn-container-single .chzn-search input{margin:1px 0;padding:4px 20px 4px 5px;border:1px solid #aaa;outline:0;background:#fff url(../img/chosen-sprite.png) no-repeat 100% -20px;background:url(../img/chosen-sprite.png) no-repeat 100% -20px,linear-gradient(#eee 1%,#fff 15%);font-family:sans-serif;font-size:1em}.chzn-container-single .chzn-drop{border-radius:0 0 4px 4px;background-clip:padding-box}.chzn-container-single-nosearch .chzn-search input{position:absolute;left:-9000px}.chzn-container-multi .chzn-choices{overflow:hidden;position:relative;height:auto!important;height:1%;margin:0;padding:0;border:1px solid #aaa;background-color:#fff;background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chzn-container-multi .chzn-choices li{float:left;list-style:none}.chzn-container-multi .chzn-choices .search-field{margin:0;padding:0;white-space:nowrap}.chzn-container-multi .chzn-choices .search-field input{height:15px;margin:1px 0;padding:5px;border:0!important;outline:0;color:#666;background:transparent!important;box-shadow:none;font-family:sans-serif;font-size:100%}.chzn-container-multi .chzn-choices .search-field .default{color:#999}.chzn-container-multi .chzn-choices .search-choice{position:relative;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;border:1px solid #aaa;border-radius:3px;color:#333;background-color:#e4e4e4;background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);line-height:13px;cursor:default;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0)}.chzn-container-multi .chzn-choices .search-choice.search-choice-disabled{padding-right:5px;border:1px solid #ccc;color:#666;background-color:#e4e4e4;background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0)}.chzn-container-multi .chzn-choices .search-choice-focus{background:#d4d4d4}.chzn-container-multi .chzn-choices .search-choice .search-choice-close{display:block;position:absolute;top:4px;right:3px;width:12px;height:12px;background:url(../img/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover,.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close{background-position:-42px -10px}.chzn-container .chzn-results{overflow-x:hidden;overflow-y:auto;position:relative;max-height:240px;margin:0 4px 4px 0;padding:0 0 0 4px;-webkit-overflow-scrolling:touch}.chzn-container-multi .chzn-results{margin:-1px 0 0;padding:0}.chzn-container .chzn-results li{display:none;margin:0;padding:5px 6px;line-height:15px;list-style:none}.chzn-container .chzn-results .active-result{display:list-item;cursor:pointer}.chzn-container .chzn-results .highlighted{color:#fff;background-color:#3875d7;background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0)}.chzn-container .chzn-results li em{background:#feffde;font-style:normal}.chzn-container .chzn-results .highlighted em{background:0 0}.chzn-container .chzn-results .no-results{display:list-item;background:#f4f4f4}.chzn-container .chzn-results .group-result{color:#999;font-weight:700;cursor:default}.chzn-container .chzn-results .group-option{padding-left:15px}.chzn-container-multi .chzn-drop .result-selected{display:none}.chzn-container .chzn-results-scroll{position:absolute;z-index:1;width:321px;margin:0 4px;background:#fff;text-align:center}.chzn-container .chzn-results-scroll span{display:inline-block;width:9px;height:17px;text-indent:-5000px}.chzn-container .chzn-results-scroll-down{bottom:0}.chzn-container .chzn-results-scroll-down span{background:url(../img/chosen-sprite.png) no-repeat -4px -3px}.chzn-container .chzn-results-scroll-up span{background:url(../img/chosen-sprite.png) no-repeat -22px -3px}.chzn-container-active .chzn-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chzn-container-active .chzn-single-with-drop{border:1px solid #aaa;border-bottom-right-radius:0;border-bottom-left-radius:0;background-color:#eee;background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0)}.chzn-container-active .chzn-single-with-drop div{border-left:none;background:0 0}.chzn-container-active .chzn-single-with-drop div b{background-position:-18px 2px}.chzn-container-active .chzn-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chzn-container-active .chzn-choices .search-field input{color:#111!important}.chzn-disabled{opacity:.5!important;cursor:default}.chzn-disabled .chzn-choices .search-choice .search-choice-close,.chzn-disabled .chzn-single{cursor:default}.chzn-rtl{text-align:right}.chzn-rtl .chzn-single{overflow:visible;padding:0 8px 0 0}.chzn-rtl .chzn-single span{margin-right:0;margin-left:26px;direction:rtl}.chzn-rtl .chzn-single div{right:auto;left:3px}.chzn-rtl .chzn-single abbr{right:auto;left:26px}.chzn-rtl .chzn-choices .search-field input{direction:rtl}.chzn-rtl .chzn-choices li{float:right}.chzn-rtl .chzn-choices .search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chzn-rtl .chzn-choices .search-choice .search-choice-close{right:auto;left:4px}.chzn-rtl.chzn-container-single .chzn-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chzn-rtl .chzn-results .group-option{padding-right:15px;padding-left:0}.chzn-rtl.chzn-container-active .chzn-single-with-drop div{border-right:none}.chzn-rtl .chzn-search input{padding:4px 5px 4px 20px;background:#fff url(../img/chosen-sprite.png) no-repeat -30px -20px;background:url(../img/chosen-sprite.png) no-repeat -30px -20px,linear-gradient(#eee 1%,#fff 15%);direction:rtl}.chzn-container-single.chzn-rtl .chzn-single div b{background-position:6px 2px}.chzn-container-single.chzn-rtl .chzn-single-with-drop div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chzn-container .chzn-results-scroll-down span,.chzn-container .chzn-results-scroll-up span,.chzn-container-multi .chzn-choices .search-choice .search-choice-close,.chzn-container-single .chzn-search input,.chzn-container-single .chzn-single abbr,.chzn-container-single .chzn-single div b,.chzn-rtl .chzn-search input{background-image:url(../img/chosen-sprite@2x.png)!important;background-repeat:no-repeat!important;background-size:52px 37px!important}}
css/yoast_ga_styles.css CHANGED
@@ -1,12 +1,12 @@
1
  h2#yoast_ga_title {
 
2
  font-size: 23px;
3
  font-weight: 400;
4
- padding: 9px 15px 4px 0;
5
  line-height: 29px;
6
  }
7
 
8
  .nav-tab-wrapper {
9
- margin-bottom: 0px;
10
  }
11
 
12
  .gatab {
@@ -17,20 +17,20 @@ h2#yoast_ga_title {
17
  display: block;
18
  padding: 0.5em 0.9em;
19
  border: 1px solid #ddd;
20
- background-color: #fff;
21
  border-radius: 0 3px 3px 3px;
 
22
  }
23
 
24
  .tabwrapper .gatab {
25
- background: none;
26
  border: none;
27
- padding: 0px;
28
  }
29
 
30
  .tabwrapper .gatab h2 {
 
31
  font-size: 23px;
32
  font-weight: 400;
33
- padding: 9px 15px 4px 0;
34
  }
35
 
36
  .ga-form-submit {
@@ -38,12 +38,12 @@ h2#yoast_ga_title {
38
  }
39
 
40
  .ga-form-label-left {
41
- width: 250px;
42
  float: left;
 
43
  margin: 0 0 0 5px;
 
44
  font-weight: bold;
45
  cursor: default;
46
- font-size: 14px;
47
  }
48
 
49
  .ga-form-input {
@@ -61,8 +61,8 @@ h2#yoast_ga_title {
61
  display: table-cell;
62
  min-width: 850px;
63
  height: 500px;
64
- padding: 0;
65
  margin: 0;
 
66
  vertical-align: top;
67
  }
68
 
@@ -70,10 +70,10 @@ h2#yoast_ga_title {
70
  display: table-cell;
71
  width: 261px;
72
  height: 500px;
73
- padding: 0;
74
  margin: 0;
75
- vertical-align: top;
76
  padding: 20px;
 
77
  }
78
 
79
  .ga-form-input {
@@ -86,10 +86,10 @@ h2#yoast_ga_title {
86
  }
87
 
88
  .ga-form-description {
89
- color: #999999;
90
- max-width: 325px;
91
  display: block;
92
  float: right;
 
 
93
  }
94
 
95
  p.ga-topdescription {
@@ -97,10 +97,10 @@ p.ga-topdescription {
97
  }
98
 
99
  #ga-promote {
100
- border: 1px solid #ccc;
101
- background-color: #fff;
102
  max-width: 600px;
103
  padding-left: 10px;
 
 
104
  }
105
 
106
  #yoast-ga-form-settings input[type="text"] {
@@ -108,9 +108,9 @@ p.ga-topdescription {
108
  }
109
 
110
  #enter_ua {
 
111
  margin-top: 10px;
112
  padding-top: 10px;
113
- display: none;
114
  }
115
 
116
  #yoast-ga-form-text-settings-ga_general-manual_ua_code_field {
@@ -121,12 +121,13 @@ select.ga-multiple {
121
  width: 300px;
122
  height: 150px !important;
123
  }
 
124
  .wpseotab .extension {
 
125
  box-sizing: border-box;
126
  width: 350px;
127
  height: 230px;
128
  margin: 10px 20px 10px 0;
129
- float: left;
130
  border: 1px solid #ccc;
131
  }
132
 
@@ -145,6 +146,17 @@ select.ga-multiple {
145
  background-size: 130px 100px;
146
  }
147
 
 
 
 
 
 
 
 
 
 
 
 
148
  .extension a {
149
  text-decoration: none;
150
  }
@@ -154,8 +166,8 @@ select.ga-multiple {
154
  }
155
 
156
  #ga-debug-info h3 {
157
- font-size: 14px;
158
- padding-left: 16px;
159
  height: 30px;
160
  margin-top: 10px;
161
- }
 
 
1
  h2#yoast_ga_title {
2
+ padding: 9px 15px 4px 0;
3
  font-size: 23px;
4
  font-weight: 400;
 
5
  line-height: 29px;
6
  }
7
 
8
  .nav-tab-wrapper {
9
+ margin-bottom: 0;
10
  }
11
 
12
  .gatab {
17
  display: block;
18
  padding: 0.5em 0.9em;
19
  border: 1px solid #ddd;
 
20
  border-radius: 0 3px 3px 3px;
21
+ background-color: #fff;
22
  }
23
 
24
  .tabwrapper .gatab {
25
+ padding: 0;
26
  border: none;
27
+ background: none;
28
  }
29
 
30
  .tabwrapper .gatab h2 {
31
+ padding: 9px 15px 4px 0;
32
  font-size: 23px;
33
  font-weight: 400;
 
34
  }
35
 
36
  .ga-form-submit {
38
  }
39
 
40
  .ga-form-label-left {
 
41
  float: left;
42
+ width: 250px;
43
  margin: 0 0 0 5px;
44
+ font-size: 14px;
45
  font-weight: bold;
46
  cursor: default;
 
47
  }
48
 
49
  .ga-form-input {
61
  display: table-cell;
62
  min-width: 850px;
63
  height: 500px;
 
64
  margin: 0;
65
+ padding: 0;
66
  vertical-align: top;
67
  }
68
 
70
  display: table-cell;
71
  width: 261px;
72
  height: 500px;
 
73
  margin: 0;
74
+ padding: 0;
75
  padding: 20px;
76
+ vertical-align: top;
77
  }
78
 
79
  .ga-form-input {
86
  }
87
 
88
  .ga-form-description {
 
 
89
  display: block;
90
  float: right;
91
+ max-width: 325px;
92
+ color: #999;
93
  }
94
 
95
  p.ga-topdescription {
97
  }
98
 
99
  #ga-promote {
 
 
100
  max-width: 600px;
101
  padding-left: 10px;
102
+ border: 1px solid #ccc;
103
+ background-color: #fff;
104
  }
105
 
106
  #yoast-ga-form-settings input[type="text"] {
108
  }
109
 
110
  #enter_ua {
111
+ display: none;
112
  margin-top: 10px;
113
  padding-top: 10px;
 
114
  }
115
 
116
  #yoast-ga-form-text-settings-ga_general-manual_ua_code_field {
121
  width: 300px;
122
  height: 150px !important;
123
  }
124
+
125
  .wpseotab .extension {
126
+ float: left;
127
  box-sizing: border-box;
128
  width: 350px;
129
  height: 230px;
130
  margin: 10px 20px 10px 0;
 
131
  border: 1px solid #ccc;
132
  }
133
 
146
  background-size: 130px 100px;
147
  }
148
 
149
+ .wpseotab .extension button.installed {
150
+ border-color: #00a000;
151
+ background-color: #00a000;
152
+ cursor: default;
153
+ }
154
+
155
+ .wpseotab .extension .button-primary.activate-link {
156
+ border-color: #f06000;
157
+ background-color: #f18500;
158
+ }
159
+
160
  .extension a {
161
  text-decoration: none;
162
  }
166
  }
167
 
168
  #ga-debug-info h3 {
 
 
169
  height: 30px;
170
  margin-top: 10px;
171
+ padding-left: 16px;
172
+ font-size: 14px;
173
+ }
css/yoast_ga_styles.min.css ADDED
@@ -0,0 +1 @@
 
1
+ h2#yoast_ga_title{padding:9px 15px 4px 0;font-size:23px;font-weight:400;line-height:29px}.nav-tab-wrapper{margin-bottom:0}.gatab{display:none}.gatab.active{display:block;padding:.5em .9em;border:1px solid #ddd;border-radius:0 3px 3px;background-color:#fff}.tabwrapper .gatab{padding:0;border:none;background:0 0}.tabwrapper .gatab h2{padding:9px 15px 4px 0;font-size:23px;font-weight:400}.ga-form-submit{margin-top:20px}.ga-form-label-left{float:left;width:250px;margin:0 0 0 5px;font-size:14px;font-weight:700;cursor:default}.ga-form-input{margin-top:10px}#yoast-ga-wrapper{display:table;width:auto;max-width:1150px}.yoast-ga-content{display:table-cell;min-width:850px;height:500px;margin:0;padding:0;vertical-align:top}.yoast-ga-banners{display:table-cell;width:261px;height:500px;margin:0;padding:0;padding:20px;vertical-align:top}.ga-form-input{display:table;margin-bottom:20px}.ga-form-table{display:table-cell}.ga-form-description{display:block;float:right;max-width:325px;color:#999}p.ga-topdescription{max-width:600px}#ga-promote{max-width:600px;padding-left:10px;border:1px solid #ccc;background-color:#fff}#yoast-ga-form-settings input[type=text]{width:325px}#enter_ua{display:none;margin-top:10px;padding-top:10px}#yoast-ga-form-text-settings-ga_general-manual_ua_code_field{margin-top:-30px}select.ga-multiple{width:300px;height:150px!important}.wpseotab .extension{float:left;box-sizing:border-box;width:350px;height:230px;margin:10px 20px 10px 0;border:1px solid #ccc}.wpseotab .extension p{margin:0;padding:10px}.wpseotab .extension h3{box-sizing:border-box;height:110px;margin:0;padding:20px 10px 0 120px;border-bottom:1px solid #ccc;background:#fff no-repeat left 10px;background-size:130px 100px}.wpseotab .extension button.installed{border-color:#00a000;background-color:#00a000;cursor:default}.wpseotab .extension .button-primary.activate-link{border-color:#f06000;background-color:#f18500}.extension a{text-decoration:none}.ecommerce h3{background-image:url(../img/eComm_130x100.png)!important}#ga-debug-info h3{height:30px;margin-top:10px;padding-left:16px;font-size:14px}
frontend/class-frontend.php CHANGED
@@ -5,36 +5,33 @@
5
 
6
  if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
7
 
8
- class Yoast_GA_Frontend {
9
-
10
- public static $options = array();
11
 
 
 
 
12
  public function __construct() {
13
- self::$options = get_option( 'yst_ga' );
14
 
15
- if ( isset( self::$options['ga_general']['tag_links_in_rss'] ) && self::$options['ga_general']['tag_links_in_rss'] == 1 ) {
16
  add_filter( 'the_permalink_rss', array( $this, 'rsslinktagger' ), 99 );
17
  }
18
 
19
  // Check if the customer is running Universal or not (Enable in GA Settings -> Universal)
20
- if ( isset( self::$options['ga_general']['enable_universal'] ) && self::$options['ga_general']['enable_universal'] == 1 ) {
21
- require_once GAWP_PATH . 'frontend/class-universal.php';
22
  } else {
23
- require_once GAWP_PATH . 'frontend/class-ga-js.php';
24
  }
25
  }
26
 
27
- public function get_options() {
28
- return self::$options;
29
- }
30
-
31
  /**
32
  * Check if we need to show an actual tracking code
 
33
  * @return bool
34
  */
35
- public static function do_tracking() {
36
  global $current_user;
37
- $options = self::$options['ga_general'];
38
 
39
  get_currentuserinfo();
40
 
@@ -42,8 +39,8 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
42
  return true;
43
  }
44
 
45
- if ( isset( $options['ignore_users'] ) ) {
46
- if ( in_array( $current_user->roles[0], $options['ignore_users'] ) ) {
47
  return false;
48
  } else {
49
  return true;
@@ -53,13 +50,6 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
53
  }
54
  }
55
 
56
- /**
57
- * Hook a Google Analytics Javascript to track downloads and outbound links
58
- */
59
- public function add_ga_javascript() {
60
- wp_enqueue_script( 'yst_ga', GAWP_URL . 'frontend/js/yst_ga.js', array(), false, true );
61
- }
62
-
63
  /**
64
  * Parse the domain
65
  *
@@ -68,21 +58,21 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
68
  * @return array|bool
69
  */
70
  public function yoast_ga_get_domain( $uri ) {
71
- $hostPattern = "/^(http:\/\/)?([^\/]+)/i";
72
- $domainPatternUS = "/[^\.\/]+\.[^\.\/]+$/";
73
- $domainPatternUK = "/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/";
74
 
75
  $matching = preg_match( $hostPattern, $uri, $matches );
76
  if ( $matching ) {
77
  $host = $matches[2];
78
- if ( preg_match( "/.*\..*\..*\..*$/", $host ) ) {
79
  preg_match( $domainPatternUK, $host, $matches );
80
  } else {
81
  preg_match( $domainPatternUS, $host, $matches );
82
  }
83
 
84
  if ( isset( $matches[0] ) ) {
85
- return array( "domain" => $matches[0], "host" => $host );
86
  } else {
87
  return false;
88
  }
@@ -94,14 +84,14 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
94
  /**
95
  * Add the UTM source parameters in the RSS feeds to track traffic
96
  *
97
- * @param $guid
98
  *
99
  * @return string
100
  */
101
- function rsslinktagger( $guid ) {
102
  global $post;
103
  if ( is_feed() ) {
104
- if ( self::$options['ga_general']['allow_anchor'] ) {
105
  $delimiter = '#';
106
  } else {
107
  $delimiter = '?';
@@ -119,8 +109,8 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
119
  /**
120
  * Return the target with a lot of parameters
121
  *
122
- * @param $category
123
- * @param $matches
124
  *
125
  * @return array
126
  */
@@ -129,11 +119,11 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
129
  $original_url = $matches[3];
130
  $domain = $this->yoast_ga_get_domain( $matches[3] );
131
  $origin = $this->yoast_ga_get_domain( $_SERVER['HTTP_HOST'] );
132
- $options = self::$options['ga_general'];
133
- $download_extensions = explode( ",", str_replace( '.', '', $options['extensions_of_files'] ) );
134
  $extension = substr( strrchr( $original_url, '.' ), 1 );
135
 
136
  // Break out immediately if the link is not an http or https link.
 
137
  if ( $protocol !== 'http' && $protocol !== 'https' && $protocol !== 'mailto' ) {
138
  $type = null;
139
  } else {
@@ -143,12 +133,14 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
143
  $type = 'download';
144
  } else {
145
  if ( $domain['domain'] == $origin['domain'] ) {
146
- $outlinks = explode( ',', $options['track_internal_as_outbound'] );
147
-
148
- if ( count( $outlinks ) >= 1 ) {
149
- foreach ( $outlinks as $out ) {
150
- if ( strpos( $original_url, $domain['domain'] . $out ) !== false ) {
151
- $type = 'internal-as-outbound';
 
 
152
  }
153
  }
154
  }
@@ -173,21 +165,21 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
173
  'extension' => $extension,
174
  'link_attributes' => rtrim( $matches[1] . ' ' . $matches[4] ),
175
  'link_text' => $matches[5],
176
- 'original_url' => $original_url
177
  );
178
  }
179
 
180
  /**
181
  * Merge the existing onclick with a new one and append it
182
  *
183
- * @param $link_attribute
184
- * @param $onclick
185
  *
186
  * @return string
187
  */
188
  public function output_add_onclick( $link_attribute, $onclick ) {
189
  if ( preg_match( '/onclick=[\'\"](.*?;)[\'\"]/i', $link_attribute, $matches ) > 0 ) {
190
- $js_snippet_single = "onclick='" . $matches[1] . " " . $onclick . "'";
191
  $js_snippet_double = 'onclick="' . $matches[1] . ' ' . $onclick . '"';
192
 
193
  $link_attribute = str_replace( 'onclick="' . $matches[1] . '"', $js_snippet_double, $link_attribute );
@@ -196,7 +188,7 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
196
  return $link_attribute;
197
  } else {
198
  if ( ! is_null( $onclick ) ) {
199
- return 'onclick="' . $onclick . '" '.$link_attribute;
200
  } else {
201
  return $link_attribute;
202
  }
@@ -206,19 +198,19 @@ if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
206
  /**
207
  * Generate the full URL
208
  *
209
- * @param $link
210
  *
211
  * @return string
212
  */
213
  public function make_full_url( $link ) {
214
  switch ( $link['type'] ) {
215
- case "download":
216
- case "internal":
217
- case "internal-as-outbound":
218
- case "outbound":
219
  return $link['protocol'] . '://' . $link['original_url'];
220
  break;
221
- case "email":
222
  return 'mailto:' . $link['original_url'];
223
  break;
224
  }
5
 
6
  if ( ! class_exists( 'Yoast_GA_Frontend' ) ) {
7
 
8
+ class Yoast_GA_Frontend extends Yoast_GA_Options {
 
 
9
 
10
+ /**
11
+ * Class constructor
12
+ */
13
  public function __construct() {
14
+ parent::__construct();
15
 
16
+ if ( isset( $this->options['tag_links_in_rss'] ) && $this->options['tag_links_in_rss'] == 1 ) {
17
  add_filter( 'the_permalink_rss', array( $this, 'rsslinktagger' ), 99 );
18
  }
19
 
20
  // Check if the customer is running Universal or not (Enable in GA Settings -> Universal)
21
+ if ( isset( $this->options['enable_universal'] ) && $this->options['enable_universal'] == 1 ) {
22
+ require_once 'class-universal.php';
23
  } else {
24
+ require_once 'class-ga-js.php';
25
  }
26
  }
27
 
 
 
 
 
28
  /**
29
  * Check if we need to show an actual tracking code
30
+ *
31
  * @return bool
32
  */
33
+ public function do_tracking() {
34
  global $current_user;
 
35
 
36
  get_currentuserinfo();
37
 
39
  return true;
40
  }
41
 
42
+ if ( isset( $this->options['ignore_users'] ) ) {
43
+ if ( in_array( $current_user->roles[0], $this->options['ignore_users'] ) ) {
44
  return false;
45
  } else {
46
  return true;
50
  }
51
  }
52
 
 
 
 
 
 
 
 
53
  /**
54
  * Parse the domain
55
  *
58
  * @return array|bool
59
  */
60
  public function yoast_ga_get_domain( $uri ) {
61
+ $hostPattern = '/^(http:\/\/)?([^\/]+)/i';
62
+ $domainPatternUS = '/[^\.\/]+\.[^\.\/]+$/';
63
+ $domainPatternUK = '/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/';
64
 
65
  $matching = preg_match( $hostPattern, $uri, $matches );
66
  if ( $matching ) {
67
  $host = $matches[2];
68
+ if ( preg_match( '/.*\..*\..*\..*$/', $host ) ) {
69
  preg_match( $domainPatternUK, $host, $matches );
70
  } else {
71
  preg_match( $domainPatternUS, $host, $matches );
72
  }
73
 
74
  if ( isset( $matches[0] ) ) {
75
+ return array( 'domain' => $matches[0], 'host' => $host );
76
  } else {
77
  return false;
78
  }
84
  /**
85
  * Add the UTM source parameters in the RSS feeds to track traffic
86
  *
87
+ * @param string $guid
88
  *
89
  * @return string
90
  */
91
+ public function rsslinktagger( $guid ) {
92
  global $post;
93
  if ( is_feed() ) {
94
+ if ( $this->options['allow_anchor'] ) {
95
  $delimiter = '#';
96
  } else {
97
  $delimiter = '?';
109
  /**
110
  * Return the target with a lot of parameters
111
  *
112
+ * @param string $category
113
+ * @param array $matches
114
  *
115
  * @return array
116
  */
119
  $original_url = $matches[3];
120
  $domain = $this->yoast_ga_get_domain( $matches[3] );
121
  $origin = $this->yoast_ga_get_domain( $_SERVER['HTTP_HOST'] );
122
+ $download_extensions = explode( ',', str_replace( '.', '', $this->options['extensions_of_files'] ) );
 
123
  $extension = substr( strrchr( $original_url, '.' ), 1 );
124
 
125
  // Break out immediately if the link is not an http or https link.
126
+ $type = null;
127
  if ( $protocol !== 'http' && $protocol !== 'https' && $protocol !== 'mailto' ) {
128
  $type = null;
129
  } else {
133
  $type = 'download';
134
  } else {
135
  if ( $domain['domain'] == $origin['domain'] ) {
136
+ $out_links = explode( ',', $this->options['track_internal_as_outbound'] );
137
+
138
+ if ( count( $out_links ) >= 1 ) {
139
+ foreach ( $out_links as $out ) {
140
+ if ( ! empty( $original_url ) && ! empty( $domain['domain'] ) ) {
141
+ if ( strpos( $original_url, $domain['domain'] . $out ) !== false ) {
142
+ $type = 'internal-as-outbound';
143
+ }
144
  }
145
  }
146
  }
165
  'extension' => $extension,
166
  'link_attributes' => rtrim( $matches[1] . ' ' . $matches[4] ),
167
  'link_text' => $matches[5],
168
+ 'original_url' => $original_url,
169
  );
170
  }
171
 
172
  /**
173
  * Merge the existing onclick with a new one and append it
174
  *
175
+ * @param string $link_attribute
176
+ * @param string $onclick
177
  *
178
  * @return string
179
  */
180
  public function output_add_onclick( $link_attribute, $onclick ) {
181
  if ( preg_match( '/onclick=[\'\"](.*?;)[\'\"]/i', $link_attribute, $matches ) > 0 ) {
182
+ $js_snippet_single = 'onclick=\'' . $matches[1] . ' ' . $onclick . '\'';
183
  $js_snippet_double = 'onclick="' . $matches[1] . ' ' . $onclick . '"';
184
 
185
  $link_attribute = str_replace( 'onclick="' . $matches[1] . '"', $js_snippet_double, $link_attribute );
188
  return $link_attribute;
189
  } else {
190
  if ( ! is_null( $onclick ) ) {
191
+ return 'onclick="' . $onclick . '" ' . $link_attribute;
192
  } else {
193
  return $link_attribute;
194
  }
198
  /**
199
  * Generate the full URL
200
  *
201
+ * @param string $link
202
  *
203
  * @return string
204
  */
205
  public function make_full_url( $link ) {
206
  switch ( $link['type'] ) {
207
+ case 'download':
208
+ case 'internal':
209
+ case 'internal-as-outbound':
210
+ case 'outbound':
211
  return $link['protocol'] . '://' . $link['original_url'];
212
  break;
213
+ case 'email':
214
  return 'mailto:' . $link['original_url'];
215
  break;
216
  }
frontend/class-ga-js.php CHANGED
@@ -9,12 +9,13 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
9
  public $link_regex;
10
 
11
  public function __construct() {
 
 
12
  $this->link_regex = '/<a (.*?)href=[\'\"](.*?):\/*([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
13
 
14
  add_action( 'wp_head', array( $this, 'tracking' ), 8 );
15
 
16
- $options = parent::$options['ga_general'];
17
- if ( $options['track_outbound'] == 1 ) {
18
  // Check for outbound
19
  add_filter( 'the_content', array( $this, 'the_content' ), 99 );
20
  add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
@@ -31,23 +32,20 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
31
  public function tracking() {
32
  global $wp_query;
33
 
34
- $options = parent::$options['ga_general'];
35
-
36
  if ( parent::do_tracking() && ! is_preview() ) {
37
  $gaq_push = array();
38
 
39
- if ( isset( $options['subdomain_tracking'] ) && $options['subdomain_tracking'] != "" ) {
40
- $domain = $options['subdomain_tracking'];
41
  } else {
42
- $domain = NULL; // Default domain value
43
  }
44
 
45
- if ( ! isset( $options['allowanchor'] ) ) {
46
- $options['allowanchor'] = false;
47
  }
48
 
49
- global $Yoast_GA_Options;
50
- $ua_code = $Yoast_GA_Options->get_tracking_code();
51
  if ( is_null( $ua_code ) ) {
52
  return;
53
  }
@@ -58,21 +56,33 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
58
  $gaq_push[] = "'_setDomainName', '" . $domain . "'";
59
  }
60
 
61
- if ( $options['add_allow_linker'] && ! $options['allowanchor'] ) {
62
  $gaq_push[] = "'_setAllowAnchor', true";
63
  }
64
 
 
 
 
 
65
  // @todo, check for AllowLinker in GA.js? Universal only?
66
 
67
  // SSL data
68
  $gaq_push[] = "'_gat._forceSSL'";
69
 
 
 
 
 
 
 
 
 
70
  // Anonymous data
71
- if ( $options['anonymize_ips'] == 1 ) {
72
  $gaq_push[] = "'_gat._anonymizeIp'";
73
  }
74
 
75
- if ( isset( $options['allowhash'] ) && $options['allowhash'] ) {
76
  $gaq_push[] = "'_gat._anonymizeIp',true";
77
  }
78
 
@@ -82,7 +92,7 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
82
  if ( $wp_query->is_search ) {
83
  $pushstr = "'_trackPageview','/?s=";
84
  if ( $wp_query->found_posts == 0 ) {
85
- $gaq_push[] = $pushstr . "no-results:" . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
86
  } else {
87
  if ( $wp_query->found_posts == 1 ) {
88
  $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
@@ -99,18 +109,23 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
99
  }
100
  }
101
 
102
- //$push = apply_filters( 'yoast-ga-push-after-pageview', $push );
103
- $ga_settings = $options; // Assign the settings to the javascript include view
 
 
 
 
 
 
104
 
105
  // Include the tracking view
106
- if ( $options['debug_mode'] == 1 ) {
107
- require( GAWP_PATH . 'frontend/views/tracking_debug.php' );
108
  } else {
109
- require( GAWP_PATH . 'frontend/views/tracking_ga_js.php' );
110
  }
111
- }
112
- else{
113
- require( GAWP_PATH . 'frontend/views/tracking_usergroup.php' );
114
  }
115
  }
116
 
@@ -127,7 +142,7 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
127
  * Ouput tracking link
128
  *
129
  * @param string $label
130
- * @param array $matches
131
  *
132
  * @return mixed
133
  */
@@ -139,17 +154,15 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
139
  return $matches[0];
140
  }
141
 
142
- $onclick = NULL;
143
- $options = $this->get_options();
144
- $options = $options['ga_general'];
145
  $full_url = $this->make_full_url( $link );
146
 
147
  switch ( $link['type'] ) {
148
  case 'download':
149
- if ( $options['track_download_as'] == 'pageview' ) {
150
  $onclick = "_gaq.push(['_trackPageview','download/" . esc_attr( $full_url ) . "']);";
151
  } else {
152
- $onclick = "_gaq.push(['_trackEvent','download/" . esc_attr( $full_url ) . "']);";
153
  }
154
 
155
  break;
@@ -158,17 +171,17 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
158
 
159
  break;
160
  case 'internal-as-outbound':
161
- if ( ! is_null( $options['track_internal_as_label'] ) ) {
162
- $label = $options['track_internal_as_label'];
163
  } else {
164
  $label = 'int';
165
  }
166
 
167
- $onclick = "_gaq.push(['_trackEvent', '" . esc_attr ( $link['category'] ) . "-" . esc_attr ( $label ) . "', '" . esc_attr ( $full_url ) . "', '" . esc_attr ( strip_tags( $link['link_text'] ) ) . "']);";
168
 
169
  break;
170
  case 'outbound':
171
- $onclick = "_gaq.push(['_trackEvent', '" . esc_attr ( $link['category'] ) . "', '" . esc_attr ( $full_url ) . "', '" . esc_attr ( strip_tags( $link['link_text'] ) ) . "']);";
172
 
173
  break;
174
  }
@@ -265,8 +278,9 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
265
  * @return mixed
266
  */
267
  public function nav_menu( $text ) {
268
- if ( ! $this->do_tracking() )
269
  return $text;
 
270
 
271
  if ( ! is_feed() ) {
272
  $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_nav_menu' ), $text );
@@ -283,8 +297,9 @@ if ( ! class_exists( 'Yoast_GA_JS' ) ) {
283
  * @return mixed
284
  */
285
  public function comment_text( $text ) {
286
- if ( ! $this->do_tracking() )
287
  return $text;
 
288
 
289
  if ( ! is_feed() ) {
290
  $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_comment_link' ), $text );
9
  public $link_regex;
10
 
11
  public function __construct() {
12
+ parent::__construct();
13
+
14
  $this->link_regex = '/<a (.*?)href=[\'\"](.*?):\/*([^\'\"]+?)[\'\"](.*?)>(.*?)<\/a>/i';
15
 
16
  add_action( 'wp_head', array( $this, 'tracking' ), 8 );
17
 
18
+ if ( $this->options['track_outbound'] == 1 ) {
 
19
  // Check for outbound
20
  add_filter( 'the_content', array( $this, 'the_content' ), 99 );
21
  add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
32
  public function tracking() {
33
  global $wp_query;
34
 
 
 
35
  if ( parent::do_tracking() && ! is_preview() ) {
36
  $gaq_push = array();
37
 
38
+ if ( isset( $this->options['subdomain_tracking'] ) && $this->options['subdomain_tracking'] != '' ) {
39
+ $domain = $this->options['subdomain_tracking'];
40
  } else {
41
+ $domain = null; // Default domain value
42
  }
43
 
44
+ if ( ! isset( $this->options['allowanchor'] ) ) {
45
+ $this->options['allowanchor'] = false;
46
  }
47
 
48
+ $ua_code = $this->get_tracking_code();
 
49
  if ( is_null( $ua_code ) ) {
50
  return;
51
  }
56
  $gaq_push[] = "'_setDomainName', '" . $domain . "'";
57
  }
58
 
59
+ if ( $this->options['allowanchor'] ) {
60
  $gaq_push[] = "'_setAllowAnchor', true";
61
  }
62
 
63
+ if ( $this->options['add_allow_linker'] ) {
64
+ $gaq_push[] = "'_setAllowLinker', true";
65
+ }
66
+
67
  // @todo, check for AllowLinker in GA.js? Universal only?
68
 
69
  // SSL data
70
  $gaq_push[] = "'_gat._forceSSL'";
71
 
72
+ if ( ! empty( $this->options['custom_code'] ) ) {
73
+ // Add custom code to the view
74
+ $gaq_push[] = array(
75
+ 'type' => 'custom_code',
76
+ 'value' => $this->options['custom_code'],
77
+ );
78
+ }
79
+
80
  // Anonymous data
81
+ if ( $this->options['anonymize_ips'] == 1 ) {
82
  $gaq_push[] = "'_gat._anonymizeIp'";
83
  }
84
 
85
+ if ( isset( $this->options['allowhash'] ) && $this->options['allowhash'] ) {
86
  $gaq_push[] = "'_gat._anonymizeIp',true";
87
  }
88
 
92
  if ( $wp_query->is_search ) {
93
  $pushstr = "'_trackPageview','/?s=";
94
  if ( $wp_query->found_posts == 0 ) {
95
+ $gaq_push[] = $pushstr . 'no-results:' . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
96
  } else {
97
  if ( $wp_query->found_posts == 1 ) {
98
  $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
109
  }
110
  }
111
 
112
+ /**
113
+ * Filter: 'yoast-ga-push-array-ga-js' - Allows filtering of the commands to push
114
+ *
115
+ * @api array $gaq_push
116
+ */
117
+ $gaq_push = apply_filters( 'yoast-ga-push-array-ga-js', $gaq_push );
118
+
119
+ $ga_settings = $this->options; // Assign the settings to the javascript include view
120
 
121
  // Include the tracking view
122
+ if ( $this->options['debug_mode'] == 1 ) {
123
+ require( 'views/tracking-debug.php' );
124
  } else {
125
+ require( 'views/tracking-ga-js.php' );
126
  }
127
+ } else {
128
+ require( 'views/tracking-usergroup.php' );
 
129
  }
130
  }
131
 
142
  * Ouput tracking link
143
  *
144
  * @param string $label
145
+ * @param array $matches
146
  *
147
  * @return mixed
148
  */
154
  return $matches[0];
155
  }
156
 
157
+ $onclick = null;
 
 
158
  $full_url = $this->make_full_url( $link );
159
 
160
  switch ( $link['type'] ) {
161
  case 'download':
162
+ if ( $this->options['track_download_as'] == 'pageview' ) {
163
  $onclick = "_gaq.push(['_trackPageview','download/" . esc_attr( $full_url ) . "']);";
164
  } else {
165
+ $onclick = "_gaq.push(['_trackEvent','download','" . esc_attr( $full_url ) . "']);";
166
  }
167
 
168
  break;
171
 
172
  break;
173
  case 'internal-as-outbound':
174
+ if ( ! is_null( $this->options['track_internal_as_label'] ) && ! empty( $this->options['track_internal_as_label'] ) ) {
175
+ $label = $this->options['track_internal_as_label'];
176
  } else {
177
  $label = 'int';
178
  }
179
 
180
+ $onclick = "_gaq.push(['_trackEvent', '" . esc_attr( $link['category'] ) . '-' . esc_attr( $label ) . "', '" . esc_attr( $full_url ) . "', '" . esc_attr( strip_tags( $link['link_text'] ) ) . "']);";
181
 
182
  break;
183
  case 'outbound':
184
+ $onclick = "_gaq.push(['_trackEvent', '" . esc_attr( $link['category'] ) . "', '" . esc_attr( $full_url ) . "', '" . esc_attr( strip_tags( $link['link_text'] ) ) . "']);";
185
 
186
  break;
187
  }
278
  * @return mixed
279
  */
280
  public function nav_menu( $text ) {
281
+ if ( ! $this->do_tracking() ) {
282
  return $text;
283
+ }
284
 
285
  if ( ! is_feed() ) {
286
  $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_nav_menu' ), $text );
297
  * @return mixed
298
  */
299
  public function comment_text( $text ) {
300
+ if ( ! $this->do_tracking() ) {
301
  return $text;
302
+ }
303
 
304
  if ( ! is_feed() ) {
305
  $text = preg_replace_callback( $this->link_regex, array( $this, 'parse_comment_link' ), $text );
frontend/class-universal.php CHANGED
@@ -9,12 +9,13 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
9
  public $link_regex;
10
 
11
  public function __construct() {
 
 
12
  $this->link_regex = '`<a (.*?)href=[\'\"](.*?):/*([^\'\"]+)[\'\"](.*?)>(.*?)</a>`i';
13
 
14
  add_action( 'wp_head', array( $this, 'tracking' ), 8 );
15
 
16
- $options = parent::$options['ga_general'];
17
- if ( $options['track_outbound'] == 1 ) {
18
  // Check for outbound option
19
  add_filter( 'the_content', array( $this, 'the_content' ), 99 );
20
  add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
@@ -31,37 +32,33 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
31
  public function tracking() {
32
  global $wp_query;
33
 
34
- $options = parent::$options['ga_general'];
35
-
36
  if ( $this->do_tracking() && ! is_preview() ) {
37
  $gaq_push = array();
38
 
39
- if ( isset( $options['subdomain_tracking'] ) && $options['subdomain_tracking'] != "" ) {
40
- $domain = $options['subdomain_tracking'];
41
  } else {
42
  $domain = 'auto'; // Default domain value
43
  }
44
 
45
- if ( ! isset( $options['allowanchor'] ) ) {
46
- $options['allowanchor'] = false;
47
  }
48
 
49
- global $Yoast_GA_Options;
50
- $ua_code = $Yoast_GA_Options->get_tracking_code();
51
  if ( is_null( $ua_code ) ) {
52
  return;
53
  }
54
 
55
-
56
  // Set tracking code here
57
  if ( ! empty( $ua_code ) ) {
58
- if ( $options['add_allow_linker'] && ! $options['allowanchor'] ) {
59
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowLinker': true}";
60
  } else {
61
- if ( $options['allowanchor'] && ! $options['add_allow_linker'] ) {
62
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowAnchor': true}";
63
  } else {
64
- if ( $options['allowanchor'] && $options['add_allow_linker'] ) {
65
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowAnchor': true, 'allowLinker': true}";
66
  } else {
67
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "'";
@@ -72,17 +69,25 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
72
 
73
  $gaq_push[] = "'set', 'forceSSL', true";
74
 
 
 
 
 
 
 
 
 
75
  // Anonymous data
76
- if ( $options['anonymize_ips'] == 1 ) {
77
  $gaq_push[] = "'set', 'anonymizeIp', true";
78
  }
79
 
80
  // add demographics
81
- if ( $options['demographics'] ) {
82
  $gaq_push[] = "'require', 'displayfeatures'";
83
  }
84
 
85
- if ( isset( $options['allowhash'] ) && $options['allowhash'] ) {
86
  $gaq_push[] = "'_setAllowHash',false";
87
  }
88
 
@@ -92,7 +97,7 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
92
  if ( $wp_query->is_search ) {
93
  $pushstr = "'send','pageview','/?s=";
94
  if ( $wp_query->found_posts == 0 ) {
95
- $gaq_push[] = $pushstr . "no-results:" . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
96
  } else {
97
  if ( $wp_query->found_posts == 1 ) {
98
  $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
@@ -109,17 +114,23 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
109
  }
110
  }
111
 
112
- //$push = apply_filters( 'yoast-ga-push-after-pageview', $push );
113
- $ga_settings = $options; // Assign the settings to the javascript include view
 
 
 
 
 
 
114
 
115
  // Include the tracking view
116
- if ( $options['debug_mode'] == 1 ) {
117
- require( GAWP_PATH . 'frontend/views/tracking_debug.php' );
118
  } else {
119
- require( GAWP_PATH . 'frontend/views/tracking_universal.php' );
120
  }
121
  } else {
122
- require( GAWP_PATH . 'frontend/views/tracking_usergroup.php' );
123
  }
124
  }
125
 
@@ -140,13 +151,11 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
140
  }
141
 
142
  $onclick = null;
143
- $options = $this->get_options();
144
- $options = $options['ga_general'];
145
  $full_url = $this->make_full_url( $link );
146
 
147
  switch ( $link['type'] ) {
148
  case 'download':
149
- if ( $options['track_download_as'] == 'pageview' ) {
150
  $onclick = "ga('send', 'pageview', '" . esc_attr( $full_url ) . "');";
151
  } else {
152
  $onclick = "ga('send', 'event', 'download', '" . esc_attr( $full_url ) . "');";
@@ -158,17 +167,17 @@ if ( ! class_exists( 'Yoast_GA_Universal' ) ) {
158
 
159
  break;
160
  case 'internal-as-outbound':
161
- if ( ! is_null( $options['track_internal_as_label'] ) ) {
162
- $label = $options['track_internal_as_label'];
163
  } else {
164
  $label = 'int';
165
  }
166
 
167
- $onclick = "ga('send', 'event', '" . esc_attr( $link['category'] ) . "-" . esc_attr( $label ) . "', '" . esc_attr( $full_url ) . "', '" . esc_attr( strip_tags( $link['link_text'] ) ) . "');";
168
 
169
  break;
170
  case 'outbound':
171
- if ( $options['track_outbound'] == 1 ) {
172
  $onclick = "ga('send', 'event', '" . esc_attr( $link['category'] ) . "', '" . esc_attr( $full_url ) . "', '" . esc_attr( strip_tags( $link['link_text'] ) ) . "');";
173
  }
174
 
9
  public $link_regex;
10
 
11
  public function __construct() {
12
+ parent::__construct();
13
+
14
  $this->link_regex = '`<a (.*?)href=[\'\"](.*?):/*([^\'\"]+)[\'\"](.*?)>(.*?)</a>`i';
15
 
16
  add_action( 'wp_head', array( $this, 'tracking' ), 8 );
17
 
18
+ if ( $this->options['track_outbound'] == 1 ) {
 
19
  // Check for outbound option
20
  add_filter( 'the_content', array( $this, 'the_content' ), 99 );
21
  add_filter( 'widget_text', array( $this, 'widget_content' ), 99 );
32
  public function tracking() {
33
  global $wp_query;
34
 
 
 
35
  if ( $this->do_tracking() && ! is_preview() ) {
36
  $gaq_push = array();
37
 
38
+ if ( isset( $this->options['subdomain_tracking'] ) && $this->options['subdomain_tracking'] != '' ) {
39
+ $domain = $this->options['subdomain_tracking'];
40
  } else {
41
  $domain = 'auto'; // Default domain value
42
  }
43
 
44
+ if ( ! isset( $this->options['allowanchor'] ) ) {
45
+ $this->options['allowanchor'] = false;
46
  }
47
 
48
+ $ua_code = $this->get_tracking_code();
 
49
  if ( is_null( $ua_code ) ) {
50
  return;
51
  }
52
 
 
53
  // Set tracking code here
54
  if ( ! empty( $ua_code ) ) {
55
+ if ( $this->options['add_allow_linker'] && ! $this->options['allowanchor'] ) {
56
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowLinker': true}";
57
  } else {
58
+ if ( $this->options['allowanchor'] && ! $this->options['add_allow_linker'] ) {
59
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowAnchor': true}";
60
  } else {
61
+ if ( $this->options['allowanchor'] && $this->options['add_allow_linker'] ) {
62
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "', {'allowAnchor': true, 'allowLinker': true}";
63
  } else {
64
  $gaq_push[] = "'create', '" . $ua_code . "', '" . $domain . "'";
69
 
70
  $gaq_push[] = "'set', 'forceSSL', true";
71
 
72
+ if ( ! empty( $this->options['custom_code'] ) ) {
73
+ // Add custom code to the view
74
+ $gaq_push[] = array(
75
+ 'type' => 'custom_code',
76
+ 'value' => $this->options['custom_code'],
77
+ );
78
+ }
79
+
80
  // Anonymous data
81
+ if ( $this->options['anonymize_ips'] == 1 ) {
82
  $gaq_push[] = "'set', 'anonymizeIp', true";
83
  }
84
 
85
  // add demographics
86
+ if ( $this->options['demographics'] ) {
87
  $gaq_push[] = "'require', 'displayfeatures'";
88
  }
89
 
90
+ if ( isset( $this->options['allowhash'] ) && $this->options['allowhash'] ) {
91
  $gaq_push[] = "'_setAllowHash',false";
92
  }
93
 
97
  if ( $wp_query->is_search ) {
98
  $pushstr = "'send','pageview','/?s=";
99
  if ( $wp_query->found_posts == 0 ) {
100
+ $gaq_push[] = $pushstr . 'no-results:' . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=no-results'";
101
  } else {
102
  if ( $wp_query->found_posts == 1 ) {
103
  $gaq_push[] = $pushstr . rawurlencode( $wp_query->query_vars['s'] ) . "&cat=1-result'";
114
  }
115
  }
116
 
117
+ /**
118
+ * Filter: 'yoast-ga-push-array-universal' - Allows filtering of the commands to push
119
+ *
120
+ * @api array $gaq_push
121
+ */
122
+ $gaq_push = apply_filters( 'yoast-ga-push-array-universal', $gaq_push );
123
+
124
+ $ga_settings = $this->options; // Assign the settings to the javascript include view
125
 
126
  // Include the tracking view
127
+ if ( $this->options['debug_mode'] == 1 ) {
128
+ require( 'views/tracking-debug.php' );
129
  } else {
130
+ require( 'views/tracking-universal.php' );
131
  }
132
  } else {
133
+ require( 'views/tracking-usergroup.php' );
134
  }
135
  }
136
 
151
  }
152
 
153
  $onclick = null;
 
 
154
  $full_url = $this->make_full_url( $link );
155
 
156
  switch ( $link['type'] ) {
157
  case 'download':
158
+ if ( $this->options['track_download_as'] == 'pageview' ) {
159
  $onclick = "ga('send', 'pageview', '" . esc_attr( $full_url ) . "');";
160
  } else {
161
  $onclick = "ga('send', 'event', 'download', '" . esc_attr( $full_url ) . "');";
167
 
168
  break;
169
  case 'internal-as-outbound':
170
+ if ( ! is_null( $this->options['track_internal_as_label'] ) && ! empty( $this->options['track_internal_as_label'] ) ) {
171
+ $label = $this->options['track_internal_as_label'];
172
  } else {
173
  $label = 'int';
174
  }
175
 
176
+ $onclick = "ga('send', 'event', '" . esc_attr( $link['category'] ) . '-' . esc_attr( $label ) . "', '" . esc_attr( $full_url ) . "', '" . esc_attr( strip_tags( $link['link_text'] ) ) . "');";
177
 
178
  break;
179
  case 'outbound':
180
+ if ( $this->options['track_outbound'] == 1 ) {
181
  $onclick = "ga('send', 'event', '" . esc_attr( $link['category'] ) . "', '" . esc_attr( $full_url ) . "', '" . esc_attr( strip_tags( $link['link_text'] ) ) . "');";
182
  }
183
 
frontend/js/yst_ga.js DELETED
File without changes
frontend/views/{tracking_debug.php → tracking-debug.php} RENAMED
File without changes
frontend/views/tracking-ga-js.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- This site uses the Yoast Google Analytics plugin v<?php echo GAWP_VERSION; ?> - Universal disabled - https://yoast.com/wordpress/plugins/google-analytics/ -->
2
+ <script type="text/javascript">
3
+
4
+ var _gaq = _gaq || [];
5
+ <?php
6
+ // List the GA elements from the class-ga-js.php
7
+ if ( count( $gaq_push ) >= 1 ) {
8
+ foreach ( $gaq_push as $item ) {
9
+ if ( ! is_array( $item ) ) {
10
+ echo ' _gaq.push([' . $item . "]);\n";
11
+ }
12
+ elseif ( isset( $item['value'] ) ) {
13
+ echo ' '.$item['value'] . "\n";
14
+ }
15
+ }
16
+ }
17
+ ?>
18
+
19
+ (function () {
20
+ var ga = document.createElement('script');
21
+ ga.type = 'text/javascript';
22
+ ga.async = true;
23
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
24
+ var s = document.getElementsByTagName('script')[0];
25
+ s.parentNode.insertBefore(ga, s);
26
+ })();
27
+
28
+ </script>
29
+ <!-- / Yoast Google Analytics -->
frontend/views/{tracking_universal.php → tracking-universal.php} RENAMED
@@ -7,17 +7,17 @@
7
 
8
  <?php
9
  // List the GA elements from the class-ga-js.php
10
- if( count( $gaq_push )>=1 ){
11
- foreach($gaq_push as $item){
12
- echo " ga(".$item.");\n";
 
 
 
 
 
13
  }
14
  }
15
-
16
- // Output the custom code that could be added in the WP backend
17
- if( !empty( $ga_settings['custom_code'] ) ){
18
- echo " " . stripslashes( $ga_settings['custom_code'] ) . "\n";
19
- }
20
  ?>
21
 
22
  </script>
23
- <!-- / Yoast Google Analytics -->
7
 
8
  <?php
9
  // List the GA elements from the class-ga-js.php
10
+ if ( count( $gaq_push ) >= 1 ) {
11
+ foreach ( $gaq_push as $item ) {
12
+ if ( ! is_array( $item ) ) {
13
+ echo ' ga('.$item.");\n";
14
+ }
15
+ elseif ( isset( $item['value'] ) ) {
16
+ echo ' '.$item['value'] . "\n";
17
+ }
18
  }
19
  }
 
 
 
 
 
20
  ?>
21
 
22
  </script>
23
+ <!-- / Yoast Google Analytics -->
frontend/views/{tracking_usergroup.php → tracking-usergroup.php} RENAMED
File without changes
frontend/views/tracking_ga_js.php DELETED
@@ -1,26 +0,0 @@
1
- <!-- This site uses the Yoast Google Analytics plugin v<?php echo GAWP_VERSION; ?> - Universal disabled - https://yoast.com/wordpress/plugins/google-analytics/ -->
2
- <script type="text/javascript">
3
-
4
- var _gaq = _gaq || [];
5
- <?php
6
- // List the GA elements from the class-ga-js.php
7
- if( count( $gaq_push )>=1 ){
8
- foreach($gaq_push as $item){
9
- echo " _gaq.push([".$item."]);\n";
10
- }
11
- }
12
-
13
- // Output the custom code that could be added in the WP backend
14
- if( !empty( $ga_settings['custom_code'] ) ){
15
- echo " " . stripslashes( $ga_settings['custom_code'] ) . "\n";
16
- }
17
- ?>
18
-
19
- (function() {
20
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
21
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
22
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
23
- })();
24
-
25
- </script>
26
- <!-- / Yoast Google Analytics -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
googleanalytics.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Google Analytics by Yoast
4
  Plugin URI: https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&utm_medium=plugin&utm_campaign=wpgaplugin&utm_content=v504
5
  Description: This plugin makes it simple to add Google Analytics to your WordPress blog, adding lots of features, eg. error page, search result and automatic clickout and download tracking.
6
  Author: Team Yoast
7
- Version: 5.0.5
8
  Requires at least: 3.8
9
  Author URI: https://yoast.com/
10
  License: GPL v3
@@ -30,22 +30,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
30
 
31
  // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics, but has since been rewritten and refactored multiple times.
32
 
33
- define( "GAWP_VERSION", '5.0.5' );
34
 
35
- define( "GAWP_FILE", __FILE__ );
36
 
37
- define( "GAWP_URL", trailingslashit( plugin_dir_url( __FILE__ ) ) );
38
-
39
- define( "GAWP_PATH", plugin_dir_path( __FILE__ ) );
40
 
41
  if ( ! class_exists( 'Yoast_GA_Options' ) ) {
42
- require_once GAWP_PATH . 'includes/class-options.php';
43
  }
44
 
45
  // Only require the needed classes
46
  if ( is_admin() ) {
47
- require_once GAWP_PATH . 'admin/class-admin.php';
48
 
49
  } else {
50
- require_once GAWP_PATH . 'frontend/class-frontend.php';
51
  }
4
  Plugin URI: https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&utm_medium=plugin&utm_campaign=wpgaplugin&utm_content=v504
5
  Description: This plugin makes it simple to add Google Analytics to your WordPress blog, adding lots of features, eg. error page, search result and automatic clickout and download tracking.
6
  Author: Team Yoast
7
+ Version: 5.0.6
8
  Requires at least: 3.8
9
  Author URI: https://yoast.com/
10
  License: GPL v3
30
 
31
  // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics, but has since been rewritten and refactored multiple times.
32
 
33
+ define( 'GAWP_VERSION', '5.0.6' );
34
 
35
+ define( 'GAWP_FILE', __FILE__ );
36
 
37
+ define( 'GAWP_URL', trailingslashit( plugin_dir_url( __FILE__ ) ) );
 
 
38
 
39
  if ( ! class_exists( 'Yoast_GA_Options' ) ) {
40
+ require_once 'includes/class-options.php';
41
  }
42
 
43
  // Only require the needed classes
44
  if ( is_admin() ) {
45
+ require_once 'admin/class-admin.php';
46
 
47
  } else {
48
+ require_once 'frontend/class-frontend.php';
49
  }
{js → img}/chosen-sprite.png RENAMED
File without changes
img/chosen-sprite@2x.png ADDED
Binary file
img/yoast-icon.png DELETED
Binary file
includes/class-options.php CHANGED
@@ -4,7 +4,35 @@ if ( ! class_exists( 'Yoast_GA_Options' ) ) {
4
 
5
  class Yoast_GA_Options {
6
 
7
- private $options;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  /**
10
  * Constructor for the options
@@ -12,18 +40,42 @@ if ( ! class_exists( 'Yoast_GA_Options' ) ) {
12
  public function __construct() {
13
  $this->options = $this->get_options();
14
 
15
- if ( ! isset( $this->options['ga_general']['version'] ) || $this->options['ga_general']['version'] < GAWP_VERSION ) {
 
 
 
 
 
 
 
 
16
  $this->upgrade();
17
  }
18
  }
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  /**
21
  * Return the Google Analytics options
22
  *
23
  * @return mixed|void
24
  */
25
  public function get_options() {
26
- return get_option( 'yst_ga' );
 
 
27
  }
28
 
29
  /**
@@ -33,15 +85,13 @@ if ( ! class_exists( 'Yoast_GA_Options' ) ) {
33
  */
34
  public function get_tracking_code() {
35
  $tracking_code = null;
36
- $options = $this->options;
37
- $options = $options['ga_general'];
38
 
39
- if ( ! empty( $options['analytics_profile'] ) ) {
40
- $tracking_code = $options['analytics_profile'];
41
  }
42
 
43
- if ( ! empty( $options['manual_ua_code_field'] ) && ! empty( $options['manual_ua_code'] ) ) {
44
- $tracking_code = $options['manual_ua_code_field'];
45
  }
46
 
47
  return $tracking_code;
@@ -53,24 +103,24 @@ if ( ! class_exists( 'Yoast_GA_Options' ) ) {
53
  * @since 5.0.1
54
  */
55
  private function upgrade() {
56
- if ( ! isset( $this->options['ga_general']['version'] ) && is_null( $this->get_tracking_code() ) ) {
57
  $old_options = get_option( 'Yoast_Google_Analytics' );
58
 
59
  if ( isset( $old_options ) && is_array( $old_options ) ) {
60
  if ( isset( $old_options['uastring'] ) && '' !== trim( $old_options['uastring'] ) ) {
61
  // Save UA as manual UA, instead of saving all the old GA crap
62
- $this->options['ga_general']['manual_ua_code'] = 1;
63
- $this->options['ga_general']['manual_ua_code_field'] = $old_options['uastring'];
64
  }
65
 
66
  // Other settings
67
- $this->options['ga_general']['allow_anchor'] = $old_options['allowanchor'];
68
- $this->options['ga_general']['add_allow_linker'] = $old_options['allowlinker'];
69
- $this->options['ga_general']['anonymous_data'] = $old_options['anonymizeip'];
70
- $this->options['ga_general']['track_outbound'] = $old_options['trackoutbound'];
71
- $this->options['ga_general']['track_internal_as_outbound'] = $old_options['internallink'];
72
- $this->options['ga_general']['track_internal_as_label'] = $old_options['internallinklabel'];
73
- $this->options['ga_general']['extensions_of_files'] = $old_options['dlextensions'];
74
 
75
  }
76
 
@@ -78,26 +128,62 @@ if ( ! class_exists( 'Yoast_GA_Options' ) ) {
78
  }
79
 
80
  // 5.0.0 to 5.0.1 fix of ignore users array
81
- if ( ! isset( $this->options['ga_general']['version'] ) || version_compare( $this->options['ga_general']['version'], '5.0.1', '<' ) ) {
82
- if ( ! is_array( $this->options['ga_general']['ignore_users'] ) ) {
83
- $this->options['ga_general']['ignore_users'] = (array) $this->options['ga_general']['ignore_users'];
84
  }
85
  }
86
 
87
  // Check is API option already exists - if not add it
88
- $yst_ga_api = get_option('yst_ga_api');
89
- if($yst_ga_api === false) {
90
  add_option( 'yst_ga_api', array(), '', 'no' );
91
  }
92
 
 
 
 
 
 
 
 
 
93
  // Set to the current version now that we've done all needed upgrades
94
- $this->options['ga_general']['version'] = GAWP_VERSION;
95
 
96
- update_option( 'yst_ga', $this->options );
97
  }
98
- }
99
-
100
- global $Yoast_GA_Options;
101
- $Yoast_GA_Options = new Yoast_GA_Options();
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
4
 
5
  class Yoast_GA_Options {
6
 
7
+ public $options;
8
+
9
+ /**
10
+ * Holds the settings for the GA plugin and possible subplugins
11
+ *
12
+ * @var string
13
+ */
14
+ public $option_name = 'yst_ga';
15
+
16
+ /**
17
+ * Holds the prefix we use within the option to save settings
18
+ *
19
+ * @var string
20
+ */
21
+ public $option_prefix = 'ga_general';
22
+
23
+ /**
24
+ * Holds the path to the main plugin file
25
+ *
26
+ * @var string
27
+ */
28
+ public $plugin_path;
29
+
30
+ /**
31
+ * Holds the URL to the main plugin directory
32
+ *
33
+ * @var string
34
+ */
35
+ public $plugin_url;
36
 
37
  /**
38
  * Constructor for the options
40
  public function __construct() {
41
  $this->options = $this->get_options();
42
 
43
+ $this->plugin_path = plugin_dir_path( GAWP_FILE );
44
+ $this->plugin_url = trailingslashit( plugin_dir_url( GAWP_FILE ) );
45
+
46
+ if ( false == $this->options ) {
47
+ add_option( $this->option_name, $this->default_ga_values() );
48
+ $this->options = $this->get_options();
49
+ }
50
+
51
+ if ( ! isset( $this->options['version'] ) || $this->options['version'] < GAWP_VERSION ) {
52
  $this->upgrade();
53
  }
54
  }
55
 
56
+ /**
57
+ * Updates the GA option within the current option_prefix
58
+ *
59
+ * @param array $val
60
+ *
61
+ * @return bool
62
+ */
63
+ public function update_option( $val ) {
64
+ $options = get_option( $this->option_name );
65
+ $options[ $this->option_prefix ] = $val;
66
+
67
+ return update_option( $this->option_name, $options );
68
+ }
69
+
70
  /**
71
  * Return the Google Analytics options
72
  *
73
  * @return mixed|void
74
  */
75
  public function get_options() {
76
+ $options = get_option( $this->option_name );
77
+
78
+ return $options[ $this->option_prefix ];
79
  }
80
 
81
  /**
85
  */
86
  public function get_tracking_code() {
87
  $tracking_code = null;
 
 
88
 
89
+ if ( ! empty( $this->options['analytics_profile'] ) ) {
90
+ $tracking_code = $this->options['analytics_profile'];
91
  }
92
 
93
+ if ( ! empty( $this->options['manual_ua_code_field'] ) && ! empty( $this->options['manual_ua_code'] ) ) {
94
+ $tracking_code = $this->options['manual_ua_code_field'];
95
  }
96
 
97
  return $tracking_code;
103
  * @since 5.0.1
104
  */
105
  private function upgrade() {
106
+ if ( ! isset( $this->options['version'] ) && is_null( $this->get_tracking_code() ) ) {
107
  $old_options = get_option( 'Yoast_Google_Analytics' );
108
 
109
  if ( isset( $old_options ) && is_array( $old_options ) ) {
110
  if ( isset( $old_options['uastring'] ) && '' !== trim( $old_options['uastring'] ) ) {
111
  // Save UA as manual UA, instead of saving all the old GA crap
112
+ $this->options['manual_ua_code'] = 1;
113
+ $this->options['manual_ua_code_field'] = $old_options['uastring'];
114
  }
115
 
116
  // Other settings
117
+ $this->options['allow_anchor'] = $old_options['allowanchor'];
118
+ $this->options['add_allow_linker'] = $old_options['allowlinker'];
119
+ $this->options['anonymous_data'] = $old_options['anonymizeip'];
120
+ $this->options['track_outbound'] = $old_options['trackoutbound'];
121
+ $this->options['track_internal_as_outbound'] = $old_options['internallink'];
122
+ $this->options['track_internal_as_label'] = $old_options['internallinklabel'];
123
+ $this->options['extensions_of_files'] = $old_options['dlextensions'];
124
 
125
  }
126
 
128
  }
129
 
130
  // 5.0.0 to 5.0.1 fix of ignore users array
131
+ if ( ! isset( $this->options['version'] ) || version_compare( $this->options['version'], '5.0.1', '<' ) ) {
132
+ if ( ! is_array( $this->options['ignore_users'] ) ) {
133
+ $this->options['ignore_users'] = (array) $this->options['ignore_users'];
134
  }
135
  }
136
 
137
  // Check is API option already exists - if not add it
138
+ $yst_ga_api = get_option( 'yst_ga_api' );
139
+ if ( $yst_ga_api === false ) {
140
  add_option( 'yst_ga_api', array(), '', 'no' );
141
  }
142
 
143
+ // Fallback to make sure every default option has a value
144
+ $defaults = $this->default_ga_values();
145
+ foreach ( $defaults[ $this->option_prefix ] as $key => $value ) {
146
+ if ( ! isset( $this->options[ $key ] ) ) {
147
+ $this->options[ $key ] = $value;
148
+ }
149
+ }
150
+
151
  // Set to the current version now that we've done all needed upgrades
152
+ $this->options['version'] = GAWP_VERSION;
153
 
154
+ $this->update_option( $this->options );
155
  }
 
 
 
 
156
 
157
+ /**
158
+ * Set the default GA settings here
159
+ * @return array
160
+ */
161
+ public function default_ga_values() {
162
+ return array(
163
+ $this->option_prefix => array(
164
+ 'analytics_profile' => null,
165
+ 'manual_ua_code' => 0,
166
+ 'manual_ua_code_field' => null,
167
+ 'track_internal_as_outbound' => null,
168
+ 'track_internal_as_label' => null,
169
+ 'track_outbound' => 0,
170
+ 'anonymous_data' => 0,
171
+ 'enable_universal' => 0,
172
+ 'demographics' => 0,
173
+ 'ignore_users' => array( 'editor' ),
174
+ 'anonymize_ips' => null,
175
+ 'track_download_as' => 'event',
176
+ 'extensions_of_files' => 'doc,exe,js,pdf,ppt,tgz,zip,xls',
177
+ 'track_full_url' => 'domain',
178
+ 'subdomain_tracking' => null,
179
+ 'tag_links_in_rss' => 0,
180
+ 'allow_anchor' => 0,
181
+ 'add_allow_linker' => 0,
182
+ 'custom_code' => null,
183
+ 'debug_mode' => 0,
184
+ 'firebug_lite' => 0,
185
+ )
186
+ );
187
+ }
188
+ }
189
  }
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' );
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' );
js/yoast_ga_admin.js CHANGED
@@ -9,6 +9,13 @@ jQuery(document).ready(function() {
9
  jQuery(this).addClass('nav-tab-active');
10
  });
11
 
 
 
 
 
 
 
 
12
  // init
13
  var active_tab = window.location.hash.replace('#top#','');
14
 
9
  jQuery(this).addClass('nav-tab-active');
10
  });
11
 
12
+ jQuery('a.activate-link').click(function() {
13
+ jQuery('#extensions.wpseotab').removeClass('active');
14
+ jQuery('#extensions-tab').removeClass('nav-tab-active');
15
+ jQuery('#licenses.wpseotab').addClass('active');
16
+ jQuery('#licenses-tab').addClass('nav-tab-active');
17
+ });
18
+
19
  // init
20
  var active_tab = window.location.hash.replace('#top#','');
21
 
js/yoast_ga_admin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(){jQuery("#ga-tabs").find("a").click(function(){jQuery("#ga-tabs").find("a").removeClass("nav-tab-active"),jQuery(".gatab").removeClass("active");var a=jQuery(this).attr("id").replace("-tab","");jQuery("#"+a).addClass("active"),jQuery(this).addClass("nav-tab-active")}),jQuery("a.activate-link").click(function(){jQuery("#extensions.wpseotab").removeClass("active"),jQuery("#extensions-tab").removeClass("nav-tab-active"),jQuery("#licenses.wpseotab").addClass("active"),jQuery("#licenses-tab").addClass("nav-tab-active")});var a=window.location.hash.replace("#top#","");(""==a||"#_=_"==a)&&(a=jQuery(".gatab").attr("id")),jQuery("#"+a).addClass("active"),jQuery("#"+a+"-tab").addClass("nav-tab-active"),jQuery("#yoast-ga-form-checkbox-settings-manual_ua_code").click(function(){jQuery(this).is(":checked")?jQuery("#enter_ua").show():(jQuery("#enter_ua").hide(),jQuery("#yoast-ga-form-text-settings-manual_ua_code_field").attr("value",""))}),jQuery("#yoast-ga-form-checkbox-settings-manual_ua_code").is(":checked")&&jQuery("#enter_ua").show()});
languages/google-analytics-for-wordpress.pot CHANGED
@@ -1,741 +1,503 @@
1
- # Copyright (C) 2014 Google Analytics for WordPress
2
- # This file is distributed under the same license as the Google Analytics for WordPress package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Google Analytics for WordPress 4.3.5\n"
6
  "Report-Msgid-Bugs-To: "
7
  "http://wordpress.org/support/plugin/google-analytics-for-wordpress\n"
8
- "POT-Creation-Date: 2014-03-26 15:25:02+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
  "PO-Revision-Date: 2014-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: Remkus de Vries <translations@yoast.com>\n"
14
  "Language-Team: Yoast Translate <translations@yoast.com>\n"
 
15
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
16
- "X-Generator: CSL v1.x\n"
17
  "X-Poedit-Basepath: .\n"
18
  "X-Poedit-Language: English\n"
19
  "X-Poedit-Country: UNITED STATES\n"
20
- "X-Poedit-Sourcecharset: utf-8\n"
21
- "X-Poedit-Keywordslist: "
22
- "__;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_"
23
- "x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
24
  "X-Poedit-Bookmarks: \n"
25
- "X-Poedit-Searchpath-0: .\n"
26
  "X-Textdomain-Support: yes\n"
27
 
28
- #: admin/class-admin.php:30
29
- msgid "Google Analytics Configuration"
30
  msgstr ""
31
 
32
- #: admin/class-admin.php:31
33
- msgid "Google Analytics"
34
- msgstr ""
35
-
36
- #: admin/class-admin.php:129
37
- msgid ""
38
- "The maximum number of allowed custom variables in Google Analytics is 5, "
39
- "please unselect one of the other custom variables before selecting this one."
40
- msgstr ""
41
-
42
- #: admin/class-admin.php:136
43
- msgid ""
44
- "That's not a valid UA ID, please make sure it matches the expected pattern "
45
- "of: UA-XXXXXX-X, and that there are no spaces or other characters in the "
46
- "input field."
47
  msgstr ""
48
 
49
- #: admin/class-admin.php:151
50
- msgid "Having problems?"
51
  msgstr ""
52
 
53
- #: admin/class-admin.php:152
54
- msgid ""
55
- "If you're having problems with this plugin, please refer to its <a "
56
- "href='%s'>FAQ page</a>."
57
  msgstr ""
58
 
59
- #: admin/class-admin.php:162
60
- msgid "Google Analytics settings reset."
 
61
  msgstr ""
62
 
63
- #: admin/class-admin.php:165
64
- msgid "You cannot edit the Google Analytics for WordPress options."
65
  msgstr ""
66
 
67
- #: admin/class-admin.php:211
68
- msgid "Google Analytics settings updated."
69
  msgstr ""
70
 
71
- #: admin/class-admin.php:218
72
- msgid "Update Google Analytics Settings &raquo;"
73
  msgstr ""
74
 
75
- #: admin/class-admin.php:254
76
- msgid "Google Analytics for WordPress Configuration"
77
  msgstr ""
78
 
79
- #: admin/class-admin.php:266
80
- msgid "Please authenticate with Google Analytics to retrieve your tracking code:"
81
  msgstr ""
82
 
83
- #: admin/class-admin.php:266
84
- msgid "Click here to authenticate with Google"
 
 
85
  msgstr ""
86
 
87
- #: admin/class-admin.php:352
88
- msgid "Please select the correct Analytics Account"
89
  msgstr ""
90
 
91
- #: admin/class-admin.php:361
92
- msgid "Please select the correct Analytics account to track:"
93
  msgstr ""
94
 
95
- #: admin/class-admin.php:363
96
- msgid "Profile"
97
  msgstr ""
98
 
99
- #: admin/class-admin.php:375
100
  msgid ""
101
- "Please note that if you have several profiles of the same website, it "
102
- "doesn't matter which profile you select, and in fact another profile might "
103
- "show as selected later. You can check whether they're profiles for the same "
104
- "site by checking if they have the same UA code. If that's true, tracking "
105
- "will be correct."
106
  msgstr ""
107
 
108
- #: admin/class-admin.php:377
109
- msgid "Refresh this listing or switch to another account: "
110
- msgstr ""
111
-
112
- #: admin/class-admin.php:379 admin/class-admin.php:382
113
  msgid ""
114
- "Unfortunately, an error occurred while connecting to Google, please try "
115
- "again:"
116
- msgstr ""
117
-
118
- #: admin/class-admin.php:386
119
- msgid "Re-authenticate with Google"
120
- msgstr ""
121
-
122
- #: admin/class-admin.php:388
123
- msgid "Select another Analytics Profile &raquo;"
124
- msgstr ""
125
-
126
- #: admin/class-admin.php:390
127
- msgid "Manually enter your UA code: "
128
  msgstr ""
129
 
130
- #: admin/class-admin.php:395
131
- msgid "Analytics Profile"
 
 
132
  msgstr ""
133
 
134
- #: admin/class-admin.php:396
135
- msgid "Manually enter your UA code"
136
  msgstr ""
137
 
138
- #: admin/class-admin.php:399
139
- msgid "In the header (default)"
140
  msgstr ""
141
 
142
- #: admin/class-admin.php:399
143
- msgid "Insert manually"
144
  msgstr ""
145
 
146
- #: admin/class-admin.php:402
147
- msgid "Notice"
148
  msgstr ""
149
 
150
- #: admin/class-admin.php:402
151
- msgid ""
152
- "You switched your theme, please make sure your Google Analytics tracking is "
153
- "still ok. Save your settings to make sure Google Analytics gets loaded "
154
- "properly."
155
  msgstr ""
156
 
157
- #: admin/class-admin.php:405
158
  msgid ""
159
- "The header is by far the best spot to place the tracking code. If you'd "
160
- "rather place the code manually, switch to manual placement. For more info "
161
- "%sread this page%s."
162
  msgstr ""
163
 
164
- #: admin/class-admin.php:406
165
  msgid ""
166
- "%sFollow the instructions here%s to choose the location for your tracking "
167
- "code manually."
168
  msgstr ""
169
 
170
- #: admin/class-admin.php:410
171
- msgid "Where should the tracking code be placed"
 
172
  msgstr ""
173
 
174
- #: admin/class-admin.php:416
175
- msgid "Track outbound clicks &amp; downloads"
176
  msgstr ""
177
 
178
- #: admin/class-admin.php:417
179
  msgid ""
180
- "Clicks &amp; downloads will be tracked as events, you can find these under "
181
- "Content &raquo; Event Tracking in your Google Analytics reports."
182
- msgstr ""
183
-
184
- #: admin/class-admin.php:422
185
- msgid "Show advanced settings"
186
- msgstr ""
187
-
188
- #: admin/class-admin.php:423
189
- msgid "Only adviced for advanced users who know their way around Google Analytics"
190
- msgstr ""
191
-
192
- #: admin/class-admin.php:428
193
- msgid "Allow tracking of anonymous data"
194
  msgstr ""
195
 
196
- #: admin/class-admin.php:429
197
  msgid ""
198
- "By allowing us to track anonymous data we can better help you, because we "
199
- "know with which WordPress configurations, themes and plugins we should "
200
- "test. No personal data will be submitted."
201
  msgstr ""
202
 
203
- #: admin/class-admin.php:432
204
- msgid "Google Analytics Settings"
205
  msgstr ""
206
 
207
- #: admin/class-admin.php:435
208
  msgid ""
209
- "Google Analytics allows you to save up to 5 custom variables on each page, "
210
- "and this plugin helps you make the most use of these! Check which custom "
211
- "variables you'd like the plugin to save for you below. Please note that "
212
- "these will only be saved when they are actually available."
213
  msgstr ""
214
 
215
- #: admin/class-admin.php:436
216
- msgid ""
217
- "If you want to start using these custom variables, go to Visitors &raquo; "
218
- "Custom Variables in your Analytics reports."
219
  msgstr ""
220
 
221
- #: admin/class-admin.php:439
222
- msgid "Logged in Users"
223
  msgstr ""
224
 
225
- #: admin/class-admin.php:440
226
- msgid ""
227
- "Allows you to easily remove logged in users from your reports, or to "
228
- "segment by different user roles. The users primary role will be logged."
229
  msgstr ""
230
 
231
- #: admin/class-admin.php:445
232
- msgid "Post type"
233
  msgstr ""
234
 
235
- #: admin/class-admin.php:446
236
- msgid ""
237
- "Allows you to see pageviews per post type, especially useful if you use "
238
- "multiple custom post types."
239
  msgstr ""
240
 
241
- #: admin/class-admin.php:451
242
- msgid "Author Name"
243
  msgstr ""
244
 
245
- #: admin/class-admin.php:452
246
- msgid "Allows you to see pageviews per author."
247
  msgstr ""
248
 
249
- #: admin/class-admin.php:457
250
- msgid "Tags"
251
  msgstr ""
252
 
253
- #: admin/class-admin.php:458
254
- msgid "Allows you to see pageviews per tags using advanced segments."
255
  msgstr ""
256
 
257
- #: admin/class-admin.php:463
258
- msgid "Publication year"
259
  msgstr ""
260
 
261
- #: admin/class-admin.php:464
262
- msgid ""
263
- "Allows you to see pageviews per year of publication, showing you if your "
264
- "old posts still get traffic."
265
  msgstr ""
266
 
267
- #: admin/class-admin.php:469
268
- msgid "Single Category"
269
  msgstr ""
270
 
271
- #: admin/class-admin.php:470
272
- msgid ""
273
- "Allows you to see pageviews per category, works best when each post is in "
274
- "only one category."
275
  msgstr ""
276
 
277
- #: admin/class-admin.php:475
278
- msgid "All Categories"
279
  msgstr ""
280
 
281
- #: admin/class-admin.php:476
282
  msgid ""
283
- "Allows you to see pageviews per category using advanced segments, should be "
284
- "used when you use multiple categories per post."
285
  msgstr ""
286
 
287
- #: admin/class-admin.php:481
288
- msgid "Custom Variables Settings"
289
  msgstr ""
290
 
291
- #: admin/class-admin.php:486
292
- msgid "Ignore users"
293
  msgstr ""
294
 
295
- #: admin/class-admin.php:487
296
  msgid ""
297
- "Users of the role you select and higher will be ignored, so if you select "
298
- "Editor, all Editors and Administrators will be ignored."
299
  msgstr ""
300
 
301
- #: admin/class-admin.php:489
302
- msgid "Ignore no-one"
303
  msgstr ""
304
 
305
- #: admin/class-admin.php:490
306
- msgid "Administrator"
307
  msgstr ""
308
 
309
- #: admin/class-admin.php:491
310
- msgid "Editor"
311
  msgstr ""
312
 
313
- #: admin/class-admin.php:492
314
- msgid "Author"
315
  msgstr ""
316
 
317
- #: admin/class-admin.php:493
318
- msgid "Contributor"
319
  msgstr ""
320
 
321
- #: admin/class-admin.php:494
322
- msgid "Subscriber (ignores all logged in users)"
323
  msgstr ""
324
 
325
- #: admin/class-admin.php:499
326
- msgid "Track outbound clicks as pageviews"
327
  msgstr ""
328
 
329
- #: admin/class-admin.php:500
330
- msgid ""
331
- "You do not need to enable this to enable outbound click tracking, this "
332
- "changes the default behavior of tracking clicks as events to tracking them "
333
- "as pageviews. This is therefore not recommended, as this would skew your "
334
- "statistics, but <em>is</em> sometimes necessary when you need to set "
335
- "outbound clicks as goals."
336
  msgstr ""
337
 
338
- #: admin/class-admin.php:505
339
- msgid "Track downloads as pageviews"
340
  msgstr ""
341
 
342
- #: admin/class-admin.php:506
343
- msgid ""
344
- "Not recommended, as this would skew your statistics, but it does make it "
345
- "possible to track downloads as goals."
346
  msgstr ""
347
 
348
- #: admin/class-admin.php:511
349
- msgid "Extensions of files to track as downloads"
350
  msgstr ""
351
 
352
- #: admin/class-admin.php:517
353
- msgid "Prefix to use in Analytics before the tracked pageviews"
354
  msgstr ""
355
 
356
- #: admin/class-admin.php:518
357
  msgid ""
358
- "This prefix is used before all pageviews, they are then segmented "
359
- "automatically after that. If nothing is entered here, "
360
- "<code>/yoast-ga/</code> is used."
361
- msgstr ""
362
-
363
- #: admin/class-admin.php:524
364
- msgid "Track full URL of outbound clicks or just the domain"
365
  msgstr ""
366
 
367
- #: admin/class-admin.php:526
368
- msgid "Just the domain"
369
  msgstr ""
370
 
371
- #: admin/class-admin.php:527
372
- msgid "Track the complete URL"
 
 
 
373
  msgstr ""
374
 
375
- #: admin/class-admin.php:533
376
- msgid "Subdomain Tracking"
377
  msgstr ""
378
 
379
- #: admin/class-admin.php:534
380
  msgid ""
381
- "This allows you to set the domain that's set by "
382
- "%s<code>setDomainName</code>%s for tracking subdomains, if empty this will "
383
- "not be set."
 
 
384
  msgstr ""
385
 
386
- #: admin/class-admin.php:539
387
- msgid "Enable Cross Domain Tracking"
 
 
388
  msgstr ""
389
 
390
- #: admin/class-admin.php:540
391
- msgid ""
392
- "This allows you to enable %sCross-Domain Tracking%s for this site. When "
393
- "endabled <code>_setAllowLinker:</code> will be enabled if it is not already."
394
  msgstr ""
395
 
396
- #: admin/class-admin.php:545
397
- msgid "Cross-Domain Tracking, Primary Domain"
398
  msgstr ""
399
 
400
- #: admin/class-admin.php:546
401
  msgid ""
402
- "Set the primary domain used in %s<code>setDomainName</code>%s for cross "
403
- "domain tracking (eg. <code>example-petstore.com</code> ), if empty this "
404
- "will default to your configured Home URL."
 
 
405
  msgstr ""
406
 
407
- #: admin/class-admin.php:551
408
- msgid "Cross-Domain Tracking, Other Domains"
409
  msgstr ""
410
 
411
- #: admin/class-admin.php:552
412
  msgid ""
413
- "All links to these domains will have the <a "
414
- "href=\"http://code.google.com/apis/analytics/docs/tracking/gaTrackingSite."
415
- "html#multipleDomains\"><code>_link</code></a> code automatically attached. "
416
- "Separate domains/sub-domains with commas (eg. "
417
- "<code>dogs.example-petstore.com, cats.example-petstore.com</code>)"
 
418
  msgstr ""
419
 
420
- #: admin/class-admin.php:557
421
- msgid "Custom Code"
422
  msgstr ""
423
 
424
- #: admin/class-admin.php:558
425
- msgid ""
426
- "Not for the average user: this allows you to add a line of code, to be "
427
- "added before the <code>trackPageview</code> call."
428
  msgstr ""
429
 
430
- #: admin/class-admin.php:563
431
- msgid "Track AdSense"
 
 
432
  msgstr ""
433
 
434
- #: admin/class-admin.php:564
435
- msgid ""
436
- "This requires integration of your Analytics and AdSense account, for help, "
437
- "<a "
438
- "href=\"http://google.com/support/analytics/bin/answer.py?answer=92625\">"
439
- "look here</a>."
440
  msgstr ""
441
 
442
- #: admin/class-admin.php:569
443
- msgid "Host ga.js locally"
444
  msgstr ""
445
 
446
- #: admin/class-admin.php:571
447
- msgid "You have to provide a URL to your ga.js file:"
448
  msgstr ""
449
 
450
- #: admin/class-admin.php:574
451
  msgid ""
452
- "For some reasons you might want to use a locally hosted ga.js file, or "
453
- "another ga.js file, check the box and then please enter the full URL "
454
- "including http here."
455
  msgstr ""
456
 
457
- #: admin/class-admin.php:578
458
- msgid "Track extra Search Engines"
459
  msgstr ""
460
 
461
- #: admin/class-admin.php:580
462
- msgid "You can provide a custom URL to the extra search engines file if you want:"
463
  msgstr ""
464
 
465
- #: admin/class-admin.php:586
466
  msgid "Tag links in RSS feed with campaign variables"
467
  msgstr ""
468
 
469
- #: admin/class-admin.php:587
470
  msgid ""
471
  "Do not use this feature if you use FeedBurner, as FeedBurner can do this "
472
  "automatically, and better than this plugin can. Check <a "
473
  "href=\"http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;"
474
- "answer=165769\">this help page</a> for info on how to enable this feature "
475
- "in FeedBurner."
476
  msgstr ""
477
 
478
- #: admin/class-admin.php:592
479
- msgid "Add tracking to the login and registration forms"
480
  msgstr ""
481
 
482
- #: admin/class-admin.php:597
483
- msgid "Add tracking to the comment forms"
484
- msgstr ""
485
-
486
- #: admin/class-admin.php:602
487
- msgid "Use # instead of ? for Campaign tracking"
488
- msgstr ""
489
-
490
- #: admin/class-admin.php:603
491
  msgid ""
492
  "This adds a <code><a "
493
  "href=\"http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking."
494
- "html#_gat.GA_Tracker_._setAllowAnchor\">_setAllowAnchor</a></code> call to "
495
- "your tracking code, and makes RSS link tagging use a # as well."
 
496
  msgstr ""
497
 
498
- #: admin/class-admin.php:608
499
  msgid "Add <code>_setAllowLinker</code>"
500
  msgstr ""
501
 
502
- #: admin/class-admin.php:609
503
  msgid ""
504
  "This adds a <code><a "
505
  "href=\"http://code.google.com/apis/analytics/docs/gaJS/"
506
- "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker\">_"
507
- "setAllowLinker</a></code> call to your tracking code, allowing you to use "
508
- "<code>_link</code> and related functions."
509
- msgstr ""
510
-
511
- #: admin/class-admin.php:614
512
- msgid "Set <code>_setAllowHash</code> to false"
513
  msgstr ""
514
 
515
- #: admin/class-admin.php:615
516
  msgid ""
517
- "This sets <code><a "
518
- "href=\"http://code.google.com/apis/analytics/docs/gaJS/"
519
- "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowHash\">_setAllowHash</"
520
- "a></code> to false, allowing you to track subdomains etc."
521
- msgstr ""
522
-
523
- #: admin/class-admin.php:620
524
- msgid "Anonymize IP's"
525
- msgstr ""
526
-
527
- #: admin/class-admin.php:621
528
- msgid ""
529
- "This adds <code><a "
530
- "href=\"http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_"
531
- "gat._anonymizeIp\">_anonymizeIp</a></code>, telling Google Analytics to "
532
- "anonymize the information sent by the tracker objects by removing the last "
533
- "octet of the IP address prior to its storage."
534
- msgstr ""
535
-
536
- #: admin/class-admin.php:625
537
- msgid "Advanced Settings"
538
- msgstr ""
539
-
540
- #: admin/class-admin.php:630
541
- msgid "Internal links to track as outbound"
542
- msgstr ""
543
-
544
- #: admin/class-admin.php:631
545
- msgid ""
546
- "If you want to track all internal links that begin with <code>/out/</code>, "
547
- "enter <code>/out/</code> in the box above. If you have multiple prefixes "
548
- "you can separate them with comma's: <code>/out/,/recommends/</code>"
549
- msgstr ""
550
-
551
- #: admin/class-admin.php:636
552
- msgid "Label to use"
553
- msgstr ""
554
-
555
- #: admin/class-admin.php:637
556
- msgid ""
557
- "The label to use for these links, this will be added to where the click "
558
- "came from, so if the label is \"aff\", the label for a click from the "
559
- "content of an article becomes \"outbound-article-aff\"."
560
- msgstr ""
561
-
562
- #: admin/class-admin.php:641
563
- msgid "Internal Links to Track as Outbound"
564
- msgstr ""
565
-
566
- #: admin/class-admin.php:644
567
- msgid ""
568
- "The WordPress e-Commerce plugin has been detected. This plugin can "
569
- "automatically add transaction tracking for you. To do that, <a "
570
- "href=\"http://yoast.com/wordpress/google-analytics/enable-ecommerce/\">"
571
- "enable e-commerce for your reports in Google Analytics</a> and then check "
572
- "the box below."
573
- msgstr ""
574
-
575
- #: admin/class-admin.php:648 admin/class-admin.php:661
576
- msgid "Enable transaction tracking"
577
- msgstr ""
578
-
579
- #: admin/class-admin.php:651
580
- msgid "WordPress e-Commerce Settings"
581
- msgstr ""
582
-
583
- #: admin/class-admin.php:657
584
- msgid ""
585
- "The Shopp e-Commerce plugin has been detected. This plugin can "
586
- "automatically add transaction tracking for you. To do that, <a "
587
- "href=\"http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&"
588
- "amp;answer=55528\">enable e-commerce for your reports in Google "
589
- "Analytics</a> and then check the box below."
590
  msgstr ""
591
 
592
- #: admin/class-admin.php:664
593
- msgid "Shopp e-Commerce Settings"
594
  msgstr ""
595
 
596
- #: admin/class-admin.php:667
597
  msgid ""
598
  "If you want to confirm that tracking on your blog is working as it should, "
599
- "enable this option and check the console in %sFirebug%s (for Firefox), "
600
- "%sFirebug Lite%s (for other browsers) or Chrome &amp; Safari's Web "
601
- "Inspector. Be absolutely sure to disable debugging afterwards, as it is "
602
- "slower than normal tracking."
603
  msgstr ""
604
 
605
- #: admin/class-admin.php:668
606
  msgid "Note"
607
  msgstr ""
608
 
609
- #: admin/class-admin.php:668
610
  msgid "the debugging and firebug scripts are only loaded for admins."
611
  msgstr ""
612
 
613
- #: admin/class-admin.php:672
614
  msgid "Enable debug mode"
615
  msgstr ""
616
 
617
- #: admin/class-admin.php:677
618
  msgid "Enable Firebug Lite"
619
  msgstr ""
620
 
621
- #: admin/class-admin.php:680
622
- msgid "Debug Mode"
623
- msgstr ""
624
-
625
- #: admin/class-admin.php:685
626
- msgid "Do you really want to reset all settings?"
627
- msgstr ""
628
-
629
- #: admin/class-admin.php:689
630
- msgid "Reset All Settings &raquo;"
631
- msgstr ""
632
-
633
- #: admin/class-admin.php:698
634
- msgid "Help Spread the Word!"
635
- msgstr ""
636
-
637
- #: admin/class-admin.php:700
638
- msgid "Rate the plugin 5★ on WordPress.org"
639
- msgstr ""
640
-
641
- #: admin/class-admin.php:701
642
- msgid "Help out other users in the forums"
643
- msgstr ""
644
-
645
- #: admin/class-admin.php:702
646
- msgid "Blog about it & link to the %1$splugin page%2$s"
647
- msgstr ""
648
-
649
- #: admin/class-admin.php:774
650
- msgid "Google Analytics is not active."
651
- msgstr ""
652
-
653
- #: admin/class-admin.php:774
654
- msgid "You must %sselect which Analytics Profile to track%s before it can work."
655
- msgstr ""
656
-
657
- #: admin/class-pointer.php:37
658
- msgid "Help improve Google Analytics for WordPress"
659
- msgstr ""
660
-
661
- #: admin/class-pointer.php:38
662
- msgid ""
663
- "You've just installed Google Analytics for WordPress by Yoast. Please helps "
664
- "us improve it by allowing us to gather anonymous usage stats so we know "
665
- "which configurations, plugins and themes to test with."
666
- msgstr ""
667
-
668
- #: admin/class-pointer.php:43
669
- msgid "Allow tracking"
670
- msgstr ""
671
-
672
- #: admin/class-pointer.php:49
673
- msgid "Do not allow tracking"
674
- msgstr ""
675
-
676
- #: admin/yst_plugin_tools.php:54
677
- msgid "Settings"
678
- msgstr ""
679
-
680
- #: admin/yst_plugin_tools.php:170
681
- msgid "Why not do any or all of the following:"
682
- msgstr ""
683
-
684
- #: admin/yst_plugin_tools.php:172
685
- msgid "Link to it so other folks can find out about it."
686
- msgstr ""
687
-
688
- #: admin/yst_plugin_tools.php:173
689
- msgid "Give it a 5 star rating on WordPress.org."
690
- msgstr ""
691
-
692
- #: admin/yst_plugin_tools.php:174
693
- msgid "Let other people know that it works with your WordPress setup."
694
- msgstr ""
695
-
696
- #: admin/yst_plugin_tools.php:176
697
- msgid "Like this plugin?"
698
- msgstr ""
699
-
700
- #: frontend/class-frontend.php:75
701
- msgid ""
702
- "Google Analytics tracking code not shown because you haven't setup Google "
703
- "Analytics for WordPress yet."
704
- msgstr ""
705
-
706
- #: frontend/class-frontend.php:310
707
- msgid ""
708
- "Google Analytics tracking code not shown because users over level %s are "
709
- "ignored."
710
- msgstr ""
711
-
712
- #: frontend/class-frontend.php:661
713
- msgid ""
714
- "Please set Google Analytics position to \"manual\" in the settings, or "
715
- "remove this call to yoast_analytics();"
716
  msgstr ""
717
 
718
  #. Plugin Name of the plugin/theme
719
- msgid "Google Analytics for WordPress"
720
  msgstr ""
721
 
722
  #. Plugin URI of the plugin/theme
723
  msgid ""
724
- "http://yoast.com/wordpress/google-analytics/#utm_source=wordpress&utm_"
725
- "medium=plugin&utm_campaign=wpgaplugin&utm_content=v420"
726
  msgstr ""
727
 
728
  #. Description of the plugin/theme
729
  msgid ""
730
  "This plugin makes it simple to add Google Analytics to your WordPress blog, "
731
- "adding lots of features, eg. custom variables and automatic clickout and "
732
- "download tracking."
733
  msgstr ""
734
 
735
  #. Author of the plugin/theme
736
- msgid "Joost de Valk"
737
  msgstr ""
738
 
739
  #. Author URI of the plugin/theme
740
- msgid "http://yoast.com/"
741
  msgstr ""
1
+ # Copyright (C) 2014 Team Yoast
2
+ # This file is distributed under the GPL v3.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Google Analytics by Yoast 5.0.6\n"
6
  "Report-Msgid-Bugs-To: "
7
  "http://wordpress.org/support/plugin/google-analytics-for-wordpress\n"
8
+ "POT-Creation-Date: 2014-09-17 13:22:41+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
  "PO-Revision-Date: 2014-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: Remkus de Vries <translations@yoast.com>\n"
14
  "Language-Team: Yoast Translate <translations@yoast.com>\n"
15
+ "X-Generator: grunt-wp-i18n 0.4.4\n"
16
  "Plural-Forms: nplurals=2; plural=n != 1;\n"
 
17
  "X-Poedit-Basepath: .\n"
18
  "X-Poedit-Language: English\n"
19
  "X-Poedit-Country: UNITED STATES\n"
20
+ "X-Poedit-SourceCharset: utf-8\n"
21
+ "X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2; "
22
+ "_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__; esc_html__;esc_attr_e; "
23
+ "esc_html_e;esc_attr_x:1,2c; esc_html_x:1,2c;\n"
24
  "X-Poedit-Bookmarks: \n"
25
+ "X-Poedit-SearchPath-0: .\n"
26
  "X-Textdomain-Support: yes\n"
27
 
28
+ #: admin/class-admin.php:57
29
+ msgid "Settings saved!"
30
  msgstr ""
31
 
32
+ #: admin/class-admin.php:70
33
+ msgid "Please configure your %sGoogle Analytics settings%s!"
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  msgstr ""
35
 
36
+ #: admin/class-admin.php:109
37
+ msgid "FAQ"
38
  msgstr ""
39
 
40
+ #: admin/class-admin.php:112 admin/class-admin.php:153
41
+ #: admin/class-admin.php:154
42
+ msgid "Settings"
 
43
  msgstr ""
44
 
45
+ #: admin/class-admin.php:135 admin/class-admin.php:144
46
+ #: admin/class-admin.php:153 admin/class-admin.php:162
47
+ msgid "Yoast Google Analytics:"
48
  msgstr ""
49
 
50
+ #: admin/class-admin.php:135
51
+ msgid "General Settings"
52
  msgstr ""
53
 
54
+ #: admin/class-admin.php:135
55
+ msgid "Analytics"
56
  msgstr ""
57
 
58
+ #: admin/class-admin.php:144 admin/class-admin.php:145
59
+ msgid "Dashboard"
60
  msgstr ""
61
 
62
+ #: admin/class-admin.php:162 admin/pages/extensions.php:22
63
+ msgid "Extensions"
64
  msgstr ""
65
 
66
+ #: admin/class-admin.php:673
67
+ msgid "Debug information"
68
  msgstr ""
69
 
70
+ #: admin/license-manager/class-license-manager.php:137
71
+ msgid ""
72
+ "<b>Warning!</b> You're blocking external requests which means you won't be "
73
+ "able to get %s updates. Please add %s to %s."
74
  msgstr ""
75
 
76
+ #: admin/license-manager/class-license-manager.php:180
77
+ msgid "Your %s license has been activated. You have an unlimited license. "
78
  msgstr ""
79
 
80
+ #: admin/license-manager/class-license-manager.php:182
81
+ msgid "Your %s license has been activated. You have used %d/%d activations. "
82
  msgstr ""
83
 
84
+ #: admin/license-manager/class-license-manager.php:187
85
+ msgid "<a href=\"%s\">Did you know you can upgrade your license?</a>"
86
  msgstr ""
87
 
88
+ #: admin/license-manager/class-license-manager.php:191
89
  msgid ""
90
+ "<a href=\"%s\">Your license is expiring in %d days, would you like to "
91
+ "extend it?</a>"
 
 
 
92
  msgstr ""
93
 
94
+ #: admin/license-manager/class-license-manager.php:200
 
 
 
 
95
  msgid ""
96
+ "You've reached your activation limit. You must <a href=\"%s\">upgrade your "
97
+ "license</a> to use it on this site."
 
 
 
 
 
 
 
 
 
 
 
 
98
  msgstr ""
99
 
100
+ #: admin/license-manager/class-license-manager.php:203
101
+ msgid ""
102
+ "Your license has expired. You must <a href=\"%s\">extend your license</a> "
103
+ "in order to use it again."
104
  msgstr ""
105
 
106
+ #: admin/license-manager/class-license-manager.php:206
107
+ msgid "Failed to activate your license, your license key seems to be invalid."
108
  msgstr ""
109
 
110
+ #: admin/license-manager/class-license-manager.php:230
111
+ msgid "Your %s license has been deactivated."
112
  msgstr ""
113
 
114
+ #: admin/license-manager/class-license-manager.php:232
115
+ msgid "Failed to deactivate your %s license."
116
  msgstr ""
117
 
118
+ #: admin/license-manager/class-license-manager.php:267
119
+ msgid "Request error: \"%s\" (%scommon license notices%s)"
120
  msgstr ""
121
 
122
+ #: admin/license-manager/class-license-manager.php:423
123
+ msgid "%s: License Settings"
 
 
 
124
  msgstr ""
125
 
126
+ #: admin/license-manager/class-plugin-license-manager.php:73
127
  msgid ""
128
+ "%s is network activated, you can manage your license in the <a "
129
+ "href=\"%s\">network admin license page</a>."
 
130
  msgstr ""
131
 
132
+ #: admin/license-manager/class-plugin-license-manager.php:75
133
  msgid ""
134
+ "%s is network activated, please contact your site administrator to manage "
135
+ "the license."
136
  msgstr ""
137
 
138
+ #: admin/license-manager/class-theme-license-manager.php:34
139
+ #: admin/license-manager/samples/sample-plugin.php:53
140
+ msgid "%s License"
141
  msgstr ""
142
 
143
+ #: admin/license-manager/class-theme-license-manager.php:34
144
+ msgid "Theme License"
145
  msgstr ""
146
 
147
+ #: admin/license-manager/class-theme-update-manager.php:96
148
  msgid ""
149
+ "Updating this theme will lose any customizations you have made. 'Cancel' to "
150
+ "stop, 'OK' to update."
 
 
 
 
 
 
 
 
 
 
 
 
151
  msgstr ""
152
 
153
+ #: admin/license-manager/class-theme-update-manager.php:101
154
  msgid ""
155
+ "<strong>%s version %s</strong> is available. <a href=\"%s\" "
156
+ "class=\"thickbox\" title=\"%s\">Check out what's new</a> or <a href=\"%s\" "
157
+ "%s>update now</a>."
158
  msgstr ""
159
 
160
+ #: admin/license-manager/class-update-manager.php:83
161
+ msgid "%s failed to check for updates because of the following error: <em>%s</em>"
162
  msgstr ""
163
 
164
+ #: admin/license-manager/class-update-manager.php:153
165
  msgid ""
166
+ "This site has not been activated properly on yoast.com and thus cannot "
167
+ "check for future updates. Please activate your site with a valid license "
168
+ "key."
 
169
  msgstr ""
170
 
171
+ #: admin/license-manager/views/form.php:23
172
+ msgid "License status"
 
 
173
  msgstr ""
174
 
175
+ #: admin/license-manager/views/form.php:33
176
+ msgid "Toggle license status"
177
  msgstr ""
178
 
179
+ #: admin/license-manager/views/form.php:37
180
+ msgid "Deactivate License"
 
 
181
  msgstr ""
182
 
183
+ #: admin/license-manager/views/form.php:38
184
+ msgid "(deactivate your license so you can activate it on another WordPress site)"
185
  msgstr ""
186
 
187
+ #: admin/license-manager/views/form.php:42
188
+ msgid "Activate License"
 
 
189
  msgstr ""
190
 
191
+ #: admin/license-manager/views/form.php:44
192
+ msgid "Please enter a license key in the field below first."
193
  msgstr ""
194
 
195
+ #: admin/license-manager/views/form.php:52
196
+ msgid "License Key"
197
  msgstr ""
198
 
199
+ #: admin/license-manager/views/form.php:54
200
+ msgid "Paste your %s license key here.."
201
  msgstr ""
202
 
203
+ #: admin/license-manager/views/form.php:56
204
+ msgid "You defined your license key using the %s PHP constant."
205
  msgstr ""
206
 
207
+ #: admin/license-manager/views/form.php:73
208
+ msgid "Your %s license will expire on %s."
209
  msgstr ""
210
 
211
+ #: admin/license-manager/views/form.php:76
212
+ msgid "%sRenew your license now%s."
 
 
213
  msgstr ""
214
 
215
+ #: admin/pages/dashboard.php:6
216
+ msgid "Yoast Google Analytics: Dashboard"
217
  msgstr ""
218
 
219
+ #: admin/pages/extensions.php:11
220
+ msgid "Google Analytics"
 
 
221
  msgstr ""
222
 
223
+ #: admin/pages/extensions.php:11
224
+ msgid "E-Commerce tracking"
225
  msgstr ""
226
 
227
+ #: admin/pages/extensions.php:12
228
  msgid ""
229
+ "Track your E-Commerce data and transactions with this E-Commerce extension "
230
+ "for Google Analytics."
231
  msgstr ""
232
 
233
+ #: admin/pages/extensions.php:19
234
+ msgid "Yoast Google Analytics: Extensions"
235
  msgstr ""
236
 
237
+ #: admin/pages/extensions.php:23
238
+ msgid "Licenses"
239
  msgstr ""
240
 
241
+ #: admin/pages/extensions.php:57
242
  msgid ""
243
+ "You have not installed any extensions for Yoast Google Analytics, so there "
244
+ "are no licenses to activate."
245
  msgstr ""
246
 
247
+ #: admin/pages/settings.php:6
248
+ msgid "Yoast Google Analytics: Settings"
249
  msgstr ""
250
 
251
+ #: admin/pages/settings.php:13
252
+ msgid "General"
253
  msgstr ""
254
 
255
+ #: admin/pages/settings.php:14
256
+ msgid "Universal"
257
  msgstr ""
258
 
259
+ #: admin/pages/settings.php:15
260
+ msgid "Advanced"
261
  msgstr ""
262
 
263
+ #: admin/pages/settings.php:16
264
+ msgid "Debug mode"
265
  msgstr ""
266
 
267
+ #: admin/pages/settings.php:25
268
+ msgid "General settings"
269
  msgstr ""
270
 
271
+ #: admin/pages/settings.php:38
272
+ msgid "Google profile"
273
  msgstr ""
274
 
275
+ #: admin/pages/settings.php:39
276
+ msgid "Authenticate with your Google account"
 
 
 
 
 
277
  msgstr ""
278
 
279
+ #: admin/pages/settings.php:42
280
+ msgid "Current UA-profile"
281
  msgstr ""
282
 
283
+ #: admin/pages/settings.php:50
284
+ msgid "Re-authenticate with your Google account"
 
 
285
  msgstr ""
286
 
287
+ #: admin/pages/settings.php:56
288
+ msgid "Manually enter your UA code"
289
  msgstr ""
290
 
291
+ #: admin/pages/settings.php:65
292
+ msgid "Track outbound click & downloads"
293
  msgstr ""
294
 
295
+ #: admin/pages/settings.php:65
296
  msgid ""
297
+ "Clicks &amp; downloads will be tracked as events, you can find these under "
298
+ "Content &raquo; Event Tracking in your Google Analytics reports."
 
 
 
 
 
299
  msgstr ""
300
 
301
+ #: admin/pages/settings.php:66
302
+ msgid "Allow tracking of anonymous data"
303
  msgstr ""
304
 
305
+ #: admin/pages/settings.php:66
306
+ msgid ""
307
+ "By allowing us to track anonymous data we can better help you, because we "
308
+ "know with which WordPress configurations, themes and plugins we should "
309
+ "test. No personal data will be submitted."
310
  msgstr ""
311
 
312
+ #: admin/pages/settings.php:67
313
+ msgid "Anonymize IP's"
314
  msgstr ""
315
 
316
+ #: admin/pages/settings.php:67
317
  msgid ""
318
+ "This adds <code><a "
319
+ "href=\"http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_"
320
+ "gat._anonymizeIp\" target=\"_blank\">_anonymizeIp</a></code>, telling "
321
+ "Google Analytics to anonymize the information sent by the tracker objects "
322
+ "by removing the last octet of the IP address prior to its storage."
323
  msgstr ""
324
 
325
+ #: admin/pages/settings.php:68
326
+ msgid ""
327
+ "Users of the role you select will be ignored, so if you select Editor, all "
328
+ "Editors will be ignored."
329
  msgstr ""
330
 
331
+ #: admin/pages/settings.php:73
332
+ msgid "Universal settings"
 
 
333
  msgstr ""
334
 
335
+ #: admin/pages/settings.php:74
336
+ msgid "Enable Universal tracking"
337
  msgstr ""
338
 
339
+ #: admin/pages/settings.php:74
340
  msgid ""
341
+ "First enable Universal tracking in your Google Analytics account. How to do "
342
+ "that, please read <a "
343
+ "href=\"http://kb.yoast.com/article/125-universal-analytics#utm_medium=kb-"
344
+ "link&utm_source=gawp-config&utm_campaign=wpgaplugin\" "
345
+ "target=\"_blank\">this guide</a> to learn how to do that."
346
  msgstr ""
347
 
348
+ #: admin/pages/settings.php:75
349
+ msgid "Enable Demographics and Interest Reports"
350
  msgstr ""
351
 
352
+ #: admin/pages/settings.php:75
353
  msgid ""
354
+ "You have to enable the Demographics in Google Analytics before you can see "
355
+ "the tracking data. We have a doc in our <a "
356
+ "href=\"http://kb.yoast.com/article/154-enable-demographics-and-interests-"
357
+ "report-in-google-analytics/#utm_medium=kb-link&utm_source=gawp-config&utm_"
358
+ "campaign=wpgaplugin\" target=\"_blank\">knowlegde base</a> about this "
359
+ "feature."
360
  msgstr ""
361
 
362
+ #: admin/pages/settings.php:80
363
+ msgid "Advanced settings"
364
  msgstr ""
365
 
366
+ #: admin/pages/settings.php:81
367
+ msgid "Track downloads as"
 
 
368
  msgstr ""
369
 
370
+ #: admin/pages/settings.php:81
371
+ msgid ""
372
+ "Not recommended, as this would skew your statistics, but it does make it "
373
+ "possible to track downloads as goals."
374
  msgstr ""
375
 
376
+ #: admin/pages/settings.php:82
377
+ msgid "Extensions of files to track as downloads"
 
 
 
 
378
  msgstr ""
379
 
380
+ #: admin/pages/settings.php:83
381
+ msgid "Track full URL of outbound clicks or just the domain"
382
  msgstr ""
383
 
384
+ #: admin/pages/settings.php:84
385
+ msgid "Subdomain tracking"
386
  msgstr ""
387
 
388
+ #: admin/pages/settings.php:84
389
  msgid ""
390
+ "This allows you to set the domain that's set by <code>setDomainName</code> "
391
+ "for tracking subdomains, if empty this will not be set."
 
392
  msgstr ""
393
 
394
+ #: admin/pages/settings.php:86
395
+ msgid "Set path for internal links to track as outbound links"
396
  msgstr ""
397
 
398
+ #: admin/pages/settings.php:87
399
+ msgid "Label for those links"
400
  msgstr ""
401
 
402
+ #: admin/pages/settings.php:89
403
  msgid "Tag links in RSS feed with campaign variables"
404
  msgstr ""
405
 
406
+ #: admin/pages/settings.php:89
407
  msgid ""
408
  "Do not use this feature if you use FeedBurner, as FeedBurner can do this "
409
  "automatically, and better than this plugin can. Check <a "
410
  "href=\"http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;"
411
+ "answer=165769\" target=\"_blank\">this help page</a> for info on how to "
412
+ "enable this feature in FeedBurner."
413
  msgstr ""
414
 
415
+ #: admin/pages/settings.php:90
416
+ msgid "Allow anchor"
417
  msgstr ""
418
 
419
+ #: admin/pages/settings.php:90
 
 
 
 
 
 
 
 
420
  msgid ""
421
  "This adds a <code><a "
422
  "href=\"http://code.google.com/apis/analytics/docs/gaJSApiCampaignTracking."
423
+ "html#_gat.GA_Tracker_._setAllowAnchor\" "
424
+ "target=\"_blank\">_setAllowAnchor</a></code> call to your tracking code, "
425
+ "and makes RSS link tagging use a # as well."
426
  msgstr ""
427
 
428
+ #: admin/pages/settings.php:91
429
  msgid "Add <code>_setAllowLinker</code>"
430
  msgstr ""
431
 
432
+ #: admin/pages/settings.php:91
433
  msgid ""
434
  "This adds a <code><a "
435
  "href=\"http://code.google.com/apis/analytics/docs/gaJS/"
436
+ "gaJSApiDomainDirectory.html#_gat.GA_Tracker_._setAllowLinker\" "
437
+ "target=\"_blank\">_setAllowLinker</a></code> call to your tracking code, "
438
+ "allowing you to use <code>_link</code> and related functions."
 
 
 
 
439
  msgstr ""
440
 
441
+ #: admin/pages/settings.php:92
442
  msgid ""
443
+ "Not for the average user: this allows you to add a line of code, to be "
444
+ "added before the <code>trackPageview</code> call."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  msgstr ""
446
 
447
+ #: admin/pages/settings.php:97
448
+ msgid "Debug settings"
449
  msgstr ""
450
 
451
+ #: admin/pages/settings.php:100
452
  msgid ""
453
  "If you want to confirm that tracking on your blog is working as it should, "
454
+ "enable these options and check the console in Firebug (for Firefox), "
455
+ "Firebug Lite (for other browsers) or Chrome & Safari's Web Inspector. Be "
456
+ "absolutely sure to disable debugging afterwards, as it is slower than "
457
+ "normal tracking."
458
  msgstr ""
459
 
460
+ #: admin/pages/settings.php:101
461
  msgid "Note"
462
  msgstr ""
463
 
464
+ #: admin/pages/settings.php:101
465
  msgid "the debugging and firebug scripts are only loaded for admins."
466
  msgstr ""
467
 
468
+ #: admin/pages/settings.php:103
469
  msgid "Enable debug mode"
470
  msgstr ""
471
 
472
+ #: admin/pages/settings.php:104
473
  msgid "Enable Firebug Lite"
474
  msgstr ""
475
 
476
+ #: admin/pages/settings.php:116
477
+ msgid "Select the users to ignore"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  msgstr ""
479
 
480
  #. Plugin Name of the plugin/theme
481
+ msgid "Google Analytics by Yoast"
482
  msgstr ""
483
 
484
  #. Plugin URI of the plugin/theme
485
  msgid ""
486
+ "https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&"
487
+ "utm_medium=plugin&utm_campaign=wpgaplugin&utm_content=v504"
488
  msgstr ""
489
 
490
  #. Description of the plugin/theme
491
  msgid ""
492
  "This plugin makes it simple to add Google Analytics to your WordPress blog, "
493
+ "adding lots of features, eg. error page, search result and automatic "
494
+ "clickout and download tracking."
495
  msgstr ""
496
 
497
  #. Author of the plugin/theme
498
+ msgid "Team Yoast"
499
  msgstr ""
500
 
501
  #. Author URI of the plugin/theme
502
+ msgid "https://yoast.com/"
503
  msgstr ""
languages/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' );
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://yoast.com/donate/
4
  Tags: analytics, google analytics, statistics, tracking, stats, google, yoast
5
  Requires at least: 3.8
6
  Tested up to: 4.0
7
- Stable tag: 5.0.5
8
 
9
  Track your WordPress site easily with the latest tracking codes and lots added data for search result pages and error pages.
10
 
@@ -49,6 +49,22 @@ This section describes how to install the plugin and get it working.
49
 
50
  == Changelog ==
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  = 5.0.5 =
53
  Release Date: September 4th, 2014
54
 
4
  Tags: analytics, google analytics, statistics, tracking, stats, google, yoast
5
  Requires at least: 3.8
6
  Tested up to: 4.0
7
+ Stable tag: 5.0.6
8
 
9
  Track your WordPress site easily with the latest tracking codes and lots added data for search result pages and error pages.
10
 
49
 
50
  == Changelog ==
51
 
52
+ = 5.0.6 =
53
+ Release Date: September 17th, 2014
54
+
55
+ * Bugfixes:
56
+ * Fixed several notices.
57
+ * Improved support for premium extensions to this plugin.
58
+ * Fixed bug where on multi-site or subdirectory installs, settings wouldn't save.
59
+ * Fix the tracking of downloads in ga.js tracking.
60
+ * Fixed a bug where custom code would be output after the send pageview instead of before.
61
+ * Fixed an empty delimiter warning.
62
+
63
+ * Enhancements:
64
+ * Improved admin icon.
65
+ * Added a filter `wpga_menu_on_top` which, when returned false, moves the analytics menu down.
66
+ * Added filters `yoast-ga-push-array-ga-js` and `yoast-ga-push-array-universal` to filter the push arrays.
67
+
68
  = 5.0.5 =
69
  Release Date: September 4th, 2014
70