SEO Ultimate - Version 7.6.5.6

Version Description

Download this release

Release Info

Developer SEO Design Solutions
Plugin Icon 128x128 SEO Ultimate
Version 7.6.5.6
Comparing to
See all releases

Code changes from version 7.6.5.5 to 7.6.5.6

modules/opengraph/opengraph.php CHANGED
@@ -1,558 +1,558 @@
1
- <?php
2
- /**
3
- * Open Graph Integrator Module
4
- *
5
- * @since 7.3
6
- */
7
-
8
- if (class_exists('SU_Module')) {
9
-
10
- class SU_OpenGraph extends SU_Module {
11
-
12
- var $namespaces_declared = false;
13
- var $jlsuggest_box_post_id = false;
14
-
15
- static function get_module_title() { return __('Open Graph Integrator', 'seo-ultimate'); }
16
- static function get_menu_title() { return __('Open Graph', 'seo-ultimate'); }
17
-
18
- function get_default_settings() {
19
- return array(
20
- 'default_post_og_type' => 'article'
21
- , 'default_page_og_type' => 'article'
22
- , 'default_post_twitter_card' => 'summary'
23
- , 'default_page_twitter_card' => 'summary'
24
- , 'default_attachment_twitter_card' => 'photo'
25
- , 'enable_og_article_author' => true
26
- );
27
- }
28
-
29
- function init() {
30
- add_filter('language_attributes', array(&$this, 'html_tag_attrs'), 1000);
31
- add_action('su_head', array(&$this, 'head_tag_output'));
32
- add_filter('su_get_setting-opengraph-twitter_site_handle', array(&$this, 'sanitize_twitter_handle'));
33
- add_filter('user_contactmethods', array(&$this, 'add_twitter_field'));
34
- add_filter('su_get_setting-opengraph-twitter_creator_handle', array(&$this, 'sanitize_twitter_handle'));
35
- }
36
-
37
- function html_tag_attrs($attrs) {
38
- $this->namespaces_declared = true;
39
- $namespace_urls = $this->get_namespace_urls();
40
-
41
- $doctype = $this->get_setting('doctype', '');
42
- switch ($doctype) {
43
- case 'xhtml':
44
- foreach ($namespace_urls as $namespace => $url) {
45
- $namespace = su_esc_attr($namespace);
46
- $url = su_esc_attr($url);
47
- $attrs .= " xmlns:$namespace=\"$url\"";
48
- }
49
- break;
50
- case 'html5':
51
- default:
52
- $attrs .= ' prefix="';
53
- $whitespace = '';
54
- foreach ($namespace_urls as $namespace => $url) {
55
- $namespace = su_esc_attr($namespace);
56
- $url = su_esc_attr($url);
57
- $attrs .= "$whitespace$namespace: $url";
58
- $whitespace = ' ';
59
- }
60
- $attrs .= '"';
61
- break;
62
- }
63
-
64
- return $attrs;
65
- }
66
-
67
- function get_namespace_urls() {
68
- return array(
69
- 'og' => 'http://ogp.me/ns#'
70
- , 'fb' => 'http://ogp.me/ns/fb#'
71
- );
72
- }
73
-
74
- function head_tag_output() {
75
- global $wp_query;
76
-
77
- $tags = $twitter_tags = array();
78
-
79
- if (is_home()) {
80
-
81
- //Type
82
- $tags['og:type'] = 'blog';
83
-
84
- //Twitter Type
85
- $twitter_tags['twitter:card'] = 'summary';
86
-
87
- //Title
88
- if (!($tags['og:title'] = $this->get_setting('home_og_title')))
89
- $tags['og:title'] = get_bloginfo('name');
90
-
91
- //Description
92
- if (!($tags['og:description'] = $this->get_setting('home_og_description')))
93
- $tags['og:description'] = get_bloginfo('description');
94
-
95
- //URL
96
- $tags['og:url'] = suwp::get_blog_home_url();
97
-
98
- //Image
99
- $tags['og:image'] = $this->get_setting('home_og_image');
100
-
101
- } elseif (is_singular()) {
102
-
103
- $post = $wp_query->get_queried_object();
104
-
105
- if (is_object($post)) {
106
- //Type
107
- if (!($tags['og:type'] = $this->get_postmeta('og_type')))
108
- $tags['og:type'] = $this->get_setting("default_{$post->post_type}_og_type");
109
-
110
- //Twitter Type
111
- if (!($twitter_tags['twitter:card'] = $this->get_postmeta('twitter_card')))
112
- $twitter_tags['twitter:card'] = $this->get_setting("default_{$post->post_type}_twitter_card");
113
-
114
- //Title
115
- if (!($tags['og:title'] = $this->get_postmeta('og_title')))
116
- $tags['og:title'] = strip_tags( apply_filters( 'single_post_title', $post->post_title ) );
117
-
118
- //Description
119
- if (!($tags['og:description'] = $this->get_postmeta('og_description')))
120
- if ($this->plugin->call_module_func('meta-descriptions', 'get_meta_desc', $meta_desc, false) && $meta_desc)
121
- $tags['og:description'] = $meta_desc;
122
-
123
- //URL
124
- $tags['og:url'] = get_permalink($post->ID);
125
-
126
- //Image
127
- $tags['og:image'] = $this->jlsuggest_value_to_url($this->get_postmeta('og_image'), true);
128
- if (!$tags['og:image']) {
129
- if ('attachment' == $post->post_type) {
130
- $tags['og:image'] = wp_get_attachment_url();
131
- } elseif (current_theme_supports('post-thumbnails') && $thumbnail_id = get_post_thumbnail_id($post->ID)) {
132
- $tags['og:image'] = wp_get_attachment_url($thumbnail_id);
133
- }
134
- }
135
-
136
- //Additional fields
137
- switch ($tags['og:type']) {
138
- case 'article':
139
-
140
- $tags['article:published_time'] = get_the_date('Y-m-d');
141
- $tags['article:modified_time'] = get_the_modified_date('Y-m-d');
142
-
143
- //Authorship generally doesn't apply to pages
144
- if (!is_page() && $this->get_setting('enable_og_article_author', true))
145
- $tags['article:author'] = get_author_posts_url($post->post_author);
146
-
147
- $single_category = (count(get_the_category()) == 1);
148
-
149
- $taxonomy_names = suwp::get_taxonomy_names();
150
- foreach ($taxonomy_names as $taxonomy_name) {
151
- if ($terms = get_the_terms(get_the_ID(), $taxonomy_name)) {
152
-
153
- if ($single_category && 'category' == $taxonomy_name)
154
- $meta_property = 'article:section';
155
- else
156
- $meta_property = 'article:tag';
157
-
158
- foreach ($terms as $term) {
159
- $tags[$meta_property][] = $term->name;
160
- }
161
- }
162
- }
163
-
164
- break;
165
- }
166
-
167
- //Author's Twitter Handle
168
- $handle = get_user_meta($post->post_author, 'twitter', true);
169
- $handle = $this->sanitize_twitter_handle($handle);
170
- $twitter_tags['twitter:creator'] = $handle;
171
- }
172
- } elseif (is_author()) {
173
-
174
- $author = $wp_query->get_queried_object();
175
-
176
- if (is_object($author)) {
177
- //Type
178
- $tags['og:type'] = 'profile';
179
-
180
- //Title
181
- $tags['og:title'] = $author->display_name;
182
-
183
- //Description
184
- $tags['og:title'] = get_the_author_meta('description', $author->ID);
185
-
186
- //Image
187
- $tags['og:image'] = false;
188
-
189
- //URL
190
- $tags['og:url'] = get_author_posts_url($author->ID, $author->user_nicename);
191
-
192
- //First Name
193
- $tags['profile:first_name'] = get_the_author_meta('first_name', $author->ID);
194
-
195
- //Last Name
196
- $tags['profile:last_name'] = get_the_author_meta('last_name', $author->ID);
197
-
198
- //Username
199
- $tags['profile:username'] = $author->user_login;
200
-
201
- //Twitter Handle
202
- $handle = get_user_meta($author->ID, 'twitter', true);
203
- $handle = $this->sanitize_twitter_handle($handle);
204
- $twitter_tags['twitter:creator'] = $handle;
205
- }
206
- } else
207
- return;
208
-
209
- if ($tags['og:type'] == 'none')
210
- $tags['og:type'] = '';
211
-
212
- if ((!isset($tags['og:image']) || !$tags['og:image']) && $tags['og:image'] !== false)
213
- $tags['og:image'] = $this->jlsuggest_value_to_url($this->get_setting('default_og_image'), true);
214
-
215
- //Site Name
216
- if (!($tags['og:site_name'] = $this->get_setting('og_site_name')))
217
- $tags['og:site_name'] = get_bloginfo('name');
218
-
219
- //FB App ID
220
- $tags['fb:app_id'] = $this->get_setting('default_fb_app_id');
221
-
222
- //Twitter Site Handle
223
- $twitter_tags['twitter:site'] = $this->get_setting('twitter_site_handle');
224
- $twitter_tags['twitter:site:id'] = $this->get_setting('twitter_site_id_handle');
225
- $twitter_tags['twitter:creator'] = $this->get_setting('twitter_creator_handle');
226
- $twitter_tags['twitter:creator:id'] = $this->get_setting('twitter_creator_id_handle');
227
- $twitter_tags['twitter:description'] = $this->get_setting('twitter_description_handle');
228
- $twitter_tags['twitter:title'] = $this->get_setting('twitter_title_handle');
229
- $twitter_tags['twitter:image:src'] = $this->get_setting('twitter_image_src_handle');
230
- $twitter_tags['twitter:image:width'] = $this->get_setting('twitter_image_width_handle');
231
- $twitter_tags['twitter:image:height'] = $this->get_setting('twitter_image_height_handle');
232
- $twitter_tags['twitter:data1'] = $this->get_setting('twitter_data1_handle');
233
- $twitter_tags['twitter:label1'] = $this->get_setting('twitter_label1_handle');
234
- $twitter_tags['twitter:data2'] = $this->get_setting('twitter_data2_handle');
235
- $twitter_tags['twitter:label2'] = $this->get_setting('twitter_label2_handle');
236
- $twitter_tags['twitter:image0:src'] = $this->get_setting('twitter_image0_src_handle');
237
- $twitter_tags['twitter:image1:src'] = $this->get_setting('twitter_image1_src_handle');
238
- $twitter_tags['twitter:image2:src'] = $this->get_setting('twitter_image2_src_handle');
239
- $twitter_tags['twitter:image3:src'] = $this->get_setting('twitter_image3_src_handle');
240
- $twitter_tags['twitter:player'] = $this->get_setting('twitter_player_handle');
241
- $twitter_tags['twitter:player:width'] = $this->get_setting('twitter_player_width_handle');
242
- $twitter_tags['twitter:player:height'] = $this->get_setting('twitter_player_height_handle');
243
- $twitter_tags['twitter:player:stream'] = $this->get_setting('twitter_player_stream_handle');
244
- $twitter_tags['twitter:app:name:iphone'] = $this->get_setting('twitter_app_name_iphone_handle');
245
- $twitter_tags['twitter:app:id:iphone'] = $this->get_setting('twitter_app_id_iphone_handle');
246
- $twitter_tags['twitter:app:url:iphone'] = $this->get_setting('twitter_app_url_iphone_handle');
247
- $twitter_tags['twitter:app:name:iphone'] = $this->get_setting('twitter_app_name_ipad_handle');
248
- $twitter_tags['twitter:app:id:iphone'] = $this->get_setting('twitter_app_id_ipad_handle');
249
- $twitter_tags['twitter:app:url:iphone'] = $this->get_setting('twitter_app_url_ipad_handle');
250
- $twitter_tags['twitter:app:name:googleplay'] = $this->get_setting('twitter_app_name_googleplay_handle');
251
- $twitter_tags['twitter:app:id:googleplay'] = $this->get_setting('twitter_app_id_googleplay_handle');
252
- $twitter_tags['twitter:app:url:googleplay'] = $this->get_setting('twitter_app_url_googleplay_handle');
253
-
254
-
255
- //Output meta tags
256
- $namespace_urls = $this->namespaces_declared ? array() : $this->get_namespace_urls();
257
- $doctype = $this->get_setting('doctype', '');
258
-
259
- switch ($doctype) {
260
- case 'xhtml':
261
- $output_formats = array('<meta%3$s name="%1$s" content="%2$s" />' => array_merge($tags, $twitter_tags));
262
- break;
263
- case 'html5':
264
- $output_formats = array('<meta%3$s property="%1$s" content="%2$s">' => array_merge($tags, $twitter_tags));
265
- break;
266
- default:
267
- $output_formats = array(
268
- '<meta%3$s property="%1$s" content="%2$s" />' => $tags
269
- , '<meta%3$s name="%1$s" content="%2$s" />' => $twitter_tags
270
- );
271
- break;
272
- }
273
-
274
- foreach ($output_formats as $html_format => $format_tags) {
275
- foreach ($format_tags as $property => $values) {
276
- foreach ((array)$values as $value) {
277
- $property = su_esc_attr($property);
278
- $value = su_esc_attr($value);
279
- if (strlen(trim($property)) && strlen(trim($value))) {
280
-
281
- $namespace_attr = '';
282
- $namespace = sustr::upto($property, ':');
283
- if (!empty($namespace_urls[$namespace])) {
284
- $a_namespace = su_esc_attr($namespace);
285
- $a_namespace_url = su_esc_attr($namespace_urls[$namespace]);
286
-
287
- switch ($doctype) {
288
- case 'xhtml':
289
- $namespace_attr = " xmlns:$a_namespace=\"$a_namespace_url\"";
290
- break;
291
- case 'html5':
292
- default:
293
- $namespace_attr = " prefix=\"$a_namespace: $a_namespace_url\"";
294
- break;
295
- }
296
- }
297
-
298
- echo "\t";
299
- printf($html_format, $property, $value, $namespace_attr);
300
- echo "\n";
301
- }
302
- }
303
- }
304
- }
305
- }
306
-
307
- function admin_page_init() {
308
- $this->jlsuggest_init();
309
- }
310
-
311
- function editor_init() {
312
- $this->jlsuggest_init();
313
- }
314
-
315
- function get_admin_page_tabs() {
316
-
317
- $postmeta_edit_tabs = $this->get_postmeta_edit_tabs(array(
318
- array(
319
- 'type' => 'dropdown'
320
- , 'options' => array_merge(array('' => __('Use default', 'seo-ultimate')), $this->get_type_options())
321
- , 'name' => 'og_type'
322
- , 'label' => __('Type', 'seo-ultimate')
323
- )
324
- , array(
325
- 'type' => 'textbox'
326
- , 'name' => 'og_title'
327
- , 'label' => __('Title', 'seo-ultimate')
328
- )
329
- , array(
330
- 'type' => 'textbox'
331
- , 'name' => 'og_description'
332
- , 'label' => __('Description', 'seo-ultimate')
333
- )
334
- , array(
335
- 'type' => 'jlsuggest'
336
- , 'name' => 'og_image'
337
- , 'label' => __('Image', 'seo-ultimate')
338
- , 'options' => array(
339
- 'params' => 'types=posttype_attachment&post_mime_type=image/*'
340
- ))
341
- ));
342
-
343
- //Remove the Image boxes from the Media tab
344
- //(it's obvious what the og:image of an attachment should be...)
345
- unset($postmeta_edit_tabs['attachment']['callback'][5][3]);
346
-
347
- return array_merge(
348
- array(
349
- array('title' => __('Sitewide Values', 'seo-ultimate'), 'id' => 'su-sitewide-values', 'callback' => 'global_tab')
350
- , array('title' => __('Default Values', 'seo-ultimate'), 'id' => 'su-default-values', 'callback' => 'defaults_tab')
351
- , array('title' => __('Settings', 'seo-ultimate'), 'id' => 'su-settings', 'callback' => 'settings_tab')
352
- , array('title' => __('Blog Homepage', 'seo-ultimate'), 'id' => 'su-homepage', 'callback' => 'home_tab')
353
- )
354
- , $postmeta_edit_tabs
355
- );
356
- }
357
-
358
- function global_tab() {
359
- $this->admin_form_table_start();
360
- $this->textbox('og_site_name', __('Site Name', 'seo-ultimate'), false, false, array(), array('placeholder' => get_bloginfo('name')));
361
- $this->textbox('default_fb_app_id', __('Facebook App ID', 'seo-ultimate'));
362
- $this->textbox('twitter_site_handle', __('@username of website', 'seo-ultimate'), false, false, array('help_text' => 'twitter:site', 'callout' => 'Twitter Card Tags'));
363
- $this->textbox('twitter_site_id_handle', __('Same as twitter:site, but the user&#8217;s Twitter ID', 'seo-ultimate'), false, false, array('help_text' => 'twitter:site:id'));
364
- $this->textbox('twitter_creator_handle', __('@username of content creator', 'seo-ultimate'), false, false, array('help_text' => 'twitter:creator'));
365
- $this->textbox('twitter_creator_id_handle', __('Twitter user ID of content creator', 'seo-ultimate'), false, false, array('help_text' => 'twitter:creator:id'));
366
- $this->textbox('twitter_description_handle', __('Description of content (maximum 200 characters)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:description'));
367
- $this->textbox('twitter_title_handle', __('Title of content (maximum 70 characters)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:title'));
368
- $this->textbox('twitter_image_src_handle', __('URL of image to use in the card. Image must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image:src'));
369
- $this->textbox('twitter_image_width_handle', __('Width of image in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image:width'));
370
- $this->textbox('twitter_image_height_handle', __('Height of image in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image:height'));
371
- $this->textbox('twitter_data1_handle', __('Top customizable data field, can be a relatively short string (ie "$3.99")', 'seo-ultimate'), false, false, array('help_text' => 'twitter:data1'));
372
- $this->textbox('twitter_label1_handle', __('Customizable label or units for the information in twitter:data1 (best practice: use all caps)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:label1'));
373
- $this->textbox('twitter_data2_handle', __('Bottom customizable data field, can be a relatively short string (ie "Seattle, WA")', 'seo-ultimate'), false, false, array('help_text' => 'twitter:data2'));
374
- $this->textbox('twitter_label2_handle', __('Customizable label or units for the information in twitter:data1 (best practice: use all caps)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:label2'));
375
- $this->textbox('twitter_image0_src_handle', __('1st image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image0:src'));
376
- $this->textbox('twitter_image1_src_handle', __('2nd image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image1:src'));
377
- $this->textbox('twitter_image2_src_handle', __('3rd image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image2:src'));
378
- $this->textbox('twitter_image3_src_handle', __('4th image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image3:src'));
379
- $this->textbox('twitter_player_handle', __(' HTTPS URL of player iframe', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player'));
380
- $this->textbox('twitter_player_width_handle', __('Width of iframe in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player:width'));
381
- $this->textbox('twitter_player_height_handle', __('Height of iframe in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player:height'));
382
- $this->textbox('twitter_player_stream_handle', __('URL to raw video or audio stream', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player:stream'));
383
- $this->textbox('twitter_app_name_iphone_handle', __('Name of your iPhone app', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:name:iphone'));
384
- $this->textbox('twitter_app_id_iphone_handle', __('Your app ID in the iTunes App Store (Note: NOT your bundle ID)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:id:iphone'));
385
- $this->textbox('twitter_app_url_iphone_handle', __('Your app&#8217;s custom URL scheme (you must include "://" after your scheme name)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:url:iphone'));
386
- $this->textbox('twitter_app_name_ipad_handle', __('Name of your iPad optimized app', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:name:ipad'));
387
- $this->textbox('twitter_app_id_ipad_handle', __('Your app ID in the iTunes App Store', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:id:ipad'));
388
- $this->textbox('twitter_app_url_ipad_handle', __('Your app&#8217;s custom URL scheme', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:url:ipad'));
389
- $this->textbox('twitter_app_name_googleplay_handle', __('Name of your Android app', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:name:googleplay'));
390
- $this->textbox('twitter_app_id_googleplay_handle', __('Your app ID in the Google Play Store', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:id:googleplay'));
391
- $this->textbox('twitter_app_url_googleplay_handle', __('Your app#8217;s custom URL scheme', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:url:googleplay'));
392
- $this->admin_form_table_end();
393
- }
394
-
395
- function defaults_tab() {
396
- $posttypes = get_post_types(array('public' => true), 'objects');
397
-
398
- $this->admin_subheader(__('Default Types', 'seo-ultimate'));
399
- $this->admin_wftable_start(array(
400
- 'posttype' => __('Post Type', 'seo-ultimate')
401
- , 'og' => __('Open Graph Type', 'seo-ultimate')
402
- , 'twitter' => __('Twitter Type', 'seo-ultimate')
403
- ));
404
- foreach ($posttypes as $posttype) {
405
- echo "<tr valign='middle'>\n";
406
- echo "\t<th class='su-opengraph-posttype' scope='row'>" . esc_html($posttype->labels->name) . "</th>\n";
407
- echo "\t<td class='su-opengraph-og'>";
408
- $this->dropdown("default_{$posttype->name}_og_type", $this->get_type_options(), false, '%s', array('in_table' => false));
409
- echo "</td>\n";
410
- echo "\t<td class='su-opengraph-twitter'>";
411
- $this->dropdown("default_{$posttype->name}_twitter_card", $this->get_twitter_type_options(), false, '%s', array('in_table' => false));
412
- echo "</td>\n";
413
- echo "</tr>\n";
414
- }
415
- $this->admin_wftable_end();
416
-
417
- $this->admin_subheader(__('Default Image', 'seo-ultimate'));
418
- $this->admin_form_table_start();
419
-
420
- $this->textblock(__('In the box below, you can specify an image URL or an image from your media library to use as a default image in the event that there is no image otherwise specified for a given webpage on your site.', 'seo-ultimate'));
421
-
422
- $this->medialib_box('default_og_image', __('Default Image', 'seo-ultimate'), 'types=posttype_attachment&post_mime_type=image/*');
423
-
424
- $this->admin_form_table_end();
425
- }
426
-
427
- function settings_tab() {
428
- $this->admin_form_table_start();
429
- $this->checkbox('enable_og_article_author', __('Include author data for posts', 'seo-ultimate'), __('Open Graph Data', 'seo-ultimate'));
430
- $this->radiobuttons('doctype', array(
431
- '' => __('Use the non-validating code prescribed by Open Graph and Twitter', 'seo-ultimate')
432
- , 'xhtml' => __('Alter the code to validate as XHTML', 'seo-ultimate')
433
- , 'html5' => __('Alter the code to validate as HTML5', 'seo-ultimate')
434
- ), __('HTML Validation', 'seo-ultimate'));
435
- $this->admin_form_table_end();
436
- }
437
-
438
- function home_tab() {
439
- $this->admin_form_table_start();
440
- $this->textbox('home_og_title', __('Blog Homepage Title', 'seo-ultimate'), false, false, array(), array('placeholder' => get_bloginfo('name')));
441
- $this->textbox('home_og_description', __('Blog Homepage Description', 'seo-ultimate'), false, false, array(), array('placeholder' => get_bloginfo('description')));
442
- $this->medialib_box('home_og_image', __('Blog Homepage Image', 'seo-ultimate'), 'types=posttype_attachment&post_mime_type=image/*');
443
- $this->admin_form_table_end();
444
- }
445
-
446
- function postmeta_fields($fields, $screen) {
447
-
448
- $fields['opengraph'][10]['og_title'] = $this->get_postmeta_textbox('og_title', __('Title:', 'seo-ultimate'));
449
- $fields['opengraph'][20]['og_description'] = $this->get_postmeta_textarea('og_description', __('Description:', 'seo-ultimate'));
450
- $fields['opengraph'][30]['og_image'] = $this->get_postmeta_medialib_box('og_image', __('Image:', 'seo-ultimate'));
451
- $fields['opengraph'][40]['og_type'] = $this->get_postmeta_dropdown('og_type', array_merge(array('' => __('Use default', 'seo-ultimate')), $this->get_type_options()), __('Open Graph Type:', 'seo-ultimate'));
452
- $fields['opengraph'][50]['twitter_card'] = $this->get_postmeta_dropdown('twitter_card', array_merge(array('' => __('Use default', 'seo-ultimate')), $this->get_twitter_type_options()), __('Twitter Type:', 'seo-ultimate'));
453
-
454
- return $fields;
455
- }
456
-
457
- function get_postmeta_jlsuggest_boxes($jls_boxes) {
458
- $this->jlsuggest_box_post_id = suwp::get_post_id();
459
- return parent::get_postmeta_jlsuggest_boxes($jls_boxes);
460
- }
461
-
462
- function get_input_element($type, $name, $value=null, $extra=false, $inputid=true) {
463
-
464
- $name_parts = explode('_', $name);
465
- if (isset($name_parts[1]) && is_numeric($post_id = $name_parts[1]))
466
- $this->jlsuggest_box_post_id = $post_id;
467
- else
468
- $this->jlsuggest_box_post_id = false;
469
-
470
- return parent::get_input_element($type, $name, $value, $extra, $inputid);
471
- }
472
-
473
- function get_jlsuggest_box($name, $value, $params='', $placeholder='') {
474
-
475
- if (empty($value) && $this->jlsuggest_box_post_id && current_theme_supports('post-thumbnails') && $thumbnail_id = get_post_thumbnail_id($this->jlsuggest_box_post_id)) {
476
- $selected_post = get_post($thumbnail_id);
477
- $placeholder = sprintf(__('Featured Image: %s', 'seo-ultimate'), $selected_post->post_title);
478
- }
479
-
480
- return parent::get_jlsuggest_box($name, $value, $params, $placeholder);
481
- }
482
-
483
- function get_type_options() {
484
- return array(
485
- 'none' => __('None', 'seo-ultimate')
486
- , __('Internet', 'seo-ultimate') => array(
487
- 'article' => __('Article', 'seo-ultimate')
488
- , 'blog' => __('Blog', 'seo-ultimate')
489
- , 'profile' => __('Profile', 'seo-ultimate')
490
- , 'website' => __('Website', 'seo-ultimate')
491
- ),__('Products', 'seo-ultimate') => array(
492
- 'book' => __('Book', 'seo-ultimate')
493
- ),__('Music', 'seo-ultimate') => array(
494
- 'music.album' => __('Album', 'seo-ultimate')
495
- , 'music.playlist' => __('Playlist', 'seo-ultimate')
496
- , 'music.radio_station' => __('Radio Station', 'seo-ultimate')
497
- , 'music.song' => __('Song', 'seo-ultimate')
498
- ),__('Videos', 'seo-ultimate') => array(
499
- 'video.movie' => __('Movie', 'seo-ultimate')
500
- , 'video.episode' => __('TV Episode', 'seo-ultimate')
501
- , 'video.tv_show' => __('TV Show', 'seo-ultimate')
502
- , 'video.other' => __('Video', 'seo-ultimate')
503
- )
504
- );
505
- }
506
-
507
- function get_twitter_type_options() {
508
- return array(
509
- 'summary' => __('Summary', 'seo-ultimate')
510
- , 'product' => __('Product', 'seo-ultimate')
511
- , 'photo' => __('Photo', 'seo-ultimate')
512
- , 'summary_large_image' => __('Summary Large Image', 'seo-ultimate')
513
- , 'gallery' => __('Gallery', 'seo-ultimate')
514
- , 'player' => __('Player', 'seo-ultimate')
515
- , 'app' => __('App', 'seo-ultimate')
516
- );
517
- }
518
-
519
- function sanitize_twitter_handle($value) {
520
- if (strpos($value, '/') === false) {
521
- $handle = ltrim($value, '@');
522
- } else {
523
- $url_parts = explode('/', $value);
524
- $handle = array_pop($url_parts);
525
- }
526
-
527
- $handle = sustr::preg_filter('a-zA-Z0-9_', $handle);
528
- $handle = trim($handle);
529
-
530
- if ($handle)
531
- $handle = "@$handle";
532
-
533
- return $handle;
534
- }
535
-
536
- function add_twitter_field( $contactmethods ) {
537
- $contactmethods['twitter'] = __('Twitter Handle', 'seo-ultimate');
538
- return $contactmethods;
539
- }
540
-
541
- function add_help_tabs($screen) {
542
-
543
- $screen->add_help_tab(array(
544
- 'id' => 'su-opengraph-overview'
545
- , 'title' => __('Overview', 'seo-ultimate')
546
- , 'content' => __("
547
- <ul>
548
- <li><strong>What it does:</strong> Open Graph Integrator makes it easy for you to convey information about your site to social networks like Facebook, Twitter, and Google+.</li>
549
- <li><strong>Why it helps:</strong> By providing this Open Graph data, you can customize how these social networks will present your site when people share it with their followers.</li>
550
- <li><strong>How to use it:</strong> The &#8220;Sitewide Values&#8221; tab lets you specify data that applies to your entire site. The &#8220;Default Values&#8221; tab lets you specify default data for your posts, pages, etc. The bulk editor tabs let you override those defaults on individual posts and pages. If the authors on your site fill in the &#8220;Twitter Handle&#8221; field which Open Graph Integrator adds to the <a href='profile.php'>profile editor</a>, Open Graph Integrator will communicate that information to Twitter as well.</li>
551
- </ul>
552
- ", 'seo-ultimate')));
553
-
554
- }
555
- }
556
-
557
- }
558
  ?>
1
+ <?php
2
+ /**
3
+ * Open Graph Integrator Module
4
+ *
5
+ * @since 7.3
6
+ */
7
+
8
+ if (class_exists('SU_Module')) {
9
+
10
+ class SU_OpenGraph extends SU_Module {
11
+
12
+ var $namespaces_declared = false;
13
+ var $jlsuggest_box_post_id = false;
14
+
15
+ static function get_module_title() { return __('Open Graph Integrator', 'seo-ultimate'); }
16
+ static function get_menu_title() { return __('Open Graph', 'seo-ultimate'); }
17
+
18
+ function get_default_settings() {
19
+ return array(
20
+ 'default_post_og_type' => 'article'
21
+ , 'default_page_og_type' => 'article'
22
+ , 'default_post_twitter_card' => 'summary'
23
+ , 'default_page_twitter_card' => 'summary'
24
+ , 'default_attachment_twitter_card' => 'photo'
25
+ , 'enable_og_article_author' => true
26
+ );
27
+ }
28
+
29
+ function init() {
30
+ add_filter('language_attributes', array(&$this, 'html_tag_attrs'), 1000);
31
+ add_action('su_head', array(&$this, 'head_tag_output'));
32
+ add_filter('su_get_setting-opengraph-twitter_site_handle', array(&$this, 'sanitize_twitter_handle'));
33
+ add_filter('user_contactmethods', array(&$this, 'add_twitter_field'));
34
+ add_filter('su_get_setting-opengraph-twitter_creator_handle', array(&$this, 'sanitize_twitter_handle'));
35
+ }
36
+
37
+ function html_tag_attrs($attrs) {
38
+ $this->namespaces_declared = true;
39
+ $namespace_urls = $this->get_namespace_urls();
40
+
41
+ $doctype = $this->get_setting('doctype', '');
42
+ switch ($doctype) {
43
+ case 'xhtml':
44
+ foreach ($namespace_urls as $namespace => $url) {
45
+ $namespace = su_esc_attr($namespace);
46
+ $url = su_esc_attr($url);
47
+ $attrs .= " xmlns:$namespace=\"$url\"";
48
+ }
49
+ break;
50
+ case 'html5':
51
+ default:
52
+ $attrs .= ' prefix="';
53
+ $whitespace = '';
54
+ foreach ($namespace_urls as $namespace => $url) {
55
+ $namespace = su_esc_attr($namespace);
56
+ $url = su_esc_attr($url);
57
+ $attrs .= "$whitespace$namespace: $url";
58
+ $whitespace = ' ';
59
+ }
60
+ $attrs .= '"';
61
+ break;
62
+ }
63
+
64
+ return $attrs;
65
+ }
66
+
67
+ function get_namespace_urls() {
68
+ return array(
69
+ 'og' => 'http://ogp.me/ns#'
70
+ , 'fb' => 'http://ogp.me/ns/fb#'
71
+ );
72
+ }
73
+
74
+ function head_tag_output() {
75
+ global $wp_query;
76
+
77
+ $tags = $twitter_tags = array();
78
+
79
+ if (is_home()) {
80
+
81
+ //Type
82
+ $tags['og:type'] = 'blog';
83
+
84
+ //Twitter Type
85
+ $twitter_tags['twitter:card'] = 'summary';
86
+
87
+ //Title
88
+ if (!($tags['og:title'] = $this->get_setting('home_og_title')))
89
+ $tags['og:title'] = get_bloginfo('name');
90
+
91
+ //Description
92
+ if (!($tags['og:description'] = $this->get_setting('home_og_description')))
93
+ $tags['og:description'] = get_bloginfo('description');
94
+
95
+ //URL
96
+ $tags['og:url'] = suwp::get_blog_home_url();
97
+
98
+ //Image
99
+ $tags['og:image'] = $this->get_setting('home_og_image');
100
+
101
+ } elseif (is_singular()) {
102
+
103
+ $post = $wp_query->get_queried_object();
104
+
105
+ if (is_object($post)) {
106
+ //Type
107
+ if (!($tags['og:type'] = $this->get_postmeta('og_type')))
108
+ $tags['og:type'] = $this->get_setting("default_{$post->post_type}_og_type");
109
+
110
+ //Twitter Type
111
+ if (!($twitter_tags['twitter:card'] = $this->get_postmeta('twitter_card')))
112
+ $twitter_tags['twitter:card'] = $this->get_setting("default_{$post->post_type}_twitter_card");
113
+
114
+ //Title
115
+ if (!($tags['og:title'] = $this->get_postmeta('og_title')))
116
+ $tags['og:title'] = strip_tags( apply_filters( 'single_post_title', $post->post_title, $post ) );
117
+
118
+ //Description
119
+ if (!($tags['og:description'] = $this->get_postmeta('og_description')))
120
+ if ($this->plugin->call_module_func('meta-descriptions', 'get_meta_desc', $meta_desc, false) && $meta_desc)
121
+ $tags['og:description'] = $meta_desc;
122
+
123
+ //URL
124
+ $tags['og:url'] = get_permalink($post->ID);
125
+
126
+ //Image
127
+ $tags['og:image'] = $this->jlsuggest_value_to_url($this->get_postmeta('og_image'), true);
128
+ if (!$tags['og:image']) {
129
+ if ('attachment' == $post->post_type) {
130
+ $tags['og:image'] = wp_get_attachment_url();
131
+ } elseif (current_theme_supports('post-thumbnails') && $thumbnail_id = get_post_thumbnail_id($post->ID)) {
132
+ $tags['og:image'] = wp_get_attachment_url($thumbnail_id);
133
+ }
134
+ }
135
+
136
+ //Additional fields
137
+ switch ($tags['og:type']) {
138
+ case 'article':
139
+
140
+ $tags['article:published_time'] = get_the_date('Y-m-d');
141
+ $tags['article:modified_time'] = get_the_modified_date('Y-m-d');
142
+
143
+ //Authorship generally doesn't apply to pages
144
+ if (!is_page() && $this->get_setting('enable_og_article_author', true))
145
+ $tags['article:author'] = get_author_posts_url($post->post_author);
146
+
147
+ $single_category = (count(get_the_category()) == 1);
148
+
149
+ $taxonomy_names = suwp::get_taxonomy_names();
150
+ foreach ($taxonomy_names as $taxonomy_name) {
151
+ if ($terms = get_the_terms(get_the_ID(), $taxonomy_name)) {
152
+
153
+ if ($single_category && 'category' == $taxonomy_name)
154
+ $meta_property = 'article:section';
155
+ else
156
+ $meta_property = 'article:tag';
157
+
158
+ foreach ($terms as $term) {
159
+ $tags[$meta_property][] = $term->name;
160
+ }
161
+ }
162
+ }
163
+
164
+ break;
165
+ }
166
+
167
+ //Author's Twitter Handle
168
+ $handle = get_user_meta($post->post_author, 'twitter', true);
169
+ $handle = $this->sanitize_twitter_handle($handle);
170
+ $twitter_tags['twitter:creator'] = $handle;
171
+ }
172
+ } elseif (is_author()) {
173
+
174
+ $author = $wp_query->get_queried_object();
175
+
176
+ if (is_object($author)) {
177
+ //Type
178
+ $tags['og:type'] = 'profile';
179
+
180
+ //Title
181
+ $tags['og:title'] = $author->display_name;
182
+
183
+ //Description
184
+ $tags['og:title'] = get_the_author_meta('description', $author->ID);
185
+
186
+ //Image
187
+ $tags['og:image'] = false;
188
+
189
+ //URL
190
+ $tags['og:url'] = get_author_posts_url($author->ID, $author->user_nicename);
191
+
192
+ //First Name
193
+ $tags['profile:first_name'] = get_the_author_meta('first_name', $author->ID);
194
+
195
+ //Last Name
196
+ $tags['profile:last_name'] = get_the_author_meta('last_name', $author->ID);
197
+
198
+ //Username
199
+ $tags['profile:username'] = $author->user_login;
200
+
201
+ //Twitter Handle
202
+ $handle = get_user_meta($author->ID, 'twitter', true);
203
+ $handle = $this->sanitize_twitter_handle($handle);
204
+ $twitter_tags['twitter:creator'] = $handle;
205
+ }
206
+ } else
207
+ return;
208
+
209
+ if ($tags['og:type'] == 'none')
210
+ $tags['og:type'] = '';
211
+
212
+ if ((!isset($tags['og:image']) || !$tags['og:image']) && $tags['og:image'] !== false)
213
+ $tags['og:image'] = $this->jlsuggest_value_to_url($this->get_setting('default_og_image'), true);
214
+
215
+ //Site Name
216
+ if (!($tags['og:site_name'] = $this->get_setting('og_site_name')))
217
+ $tags['og:site_name'] = get_bloginfo('name');
218
+
219
+ //FB App ID
220
+ $tags['fb:app_id'] = $this->get_setting('default_fb_app_id');
221
+
222
+ //Twitter Site Handle
223
+ $twitter_tags['twitter:site'] = $this->get_setting('twitter_site_handle');
224
+ $twitter_tags['twitter:site:id'] = $this->get_setting('twitter_site_id_handle');
225
+ $twitter_tags['twitter:creator'] = $this->get_setting('twitter_creator_handle');
226
+ $twitter_tags['twitter:creator:id'] = $this->get_setting('twitter_creator_id_handle');
227
+ $twitter_tags['twitter:description'] = $this->get_setting('twitter_description_handle');
228
+ $twitter_tags['twitter:title'] = $this->get_setting('twitter_title_handle');
229
+ $twitter_tags['twitter:image:src'] = $this->get_setting('twitter_image_src_handle');
230
+ $twitter_tags['twitter:image:width'] = $this->get_setting('twitter_image_width_handle');
231
+ $twitter_tags['twitter:image:height'] = $this->get_setting('twitter_image_height_handle');
232
+ $twitter_tags['twitter:data1'] = $this->get_setting('twitter_data1_handle');
233
+ $twitter_tags['twitter:label1'] = $this->get_setting('twitter_label1_handle');
234
+ $twitter_tags['twitter:data2'] = $this->get_setting('twitter_data2_handle');
235
+ $twitter_tags['twitter:label2'] = $this->get_setting('twitter_label2_handle');
236
+ $twitter_tags['twitter:image0:src'] = $this->get_setting('twitter_image0_src_handle');
237
+ $twitter_tags['twitter:image1:src'] = $this->get_setting('twitter_image1_src_handle');
238
+ $twitter_tags['twitter:image2:src'] = $this->get_setting('twitter_image2_src_handle');
239
+ $twitter_tags['twitter:image3:src'] = $this->get_setting('twitter_image3_src_handle');
240
+ $twitter_tags['twitter:player'] = $this->get_setting('twitter_player_handle');
241
+ $twitter_tags['twitter:player:width'] = $this->get_setting('twitter_player_width_handle');
242
+ $twitter_tags['twitter:player:height'] = $this->get_setting('twitter_player_height_handle');
243
+ $twitter_tags['twitter:player:stream'] = $this->get_setting('twitter_player_stream_handle');
244
+ $twitter_tags['twitter:app:name:iphone'] = $this->get_setting('twitter_app_name_iphone_handle');
245
+ $twitter_tags['twitter:app:id:iphone'] = $this->get_setting('twitter_app_id_iphone_handle');
246
+ $twitter_tags['twitter:app:url:iphone'] = $this->get_setting('twitter_app_url_iphone_handle');
247
+ $twitter_tags['twitter:app:name:iphone'] = $this->get_setting('twitter_app_name_ipad_handle');
248
+ $twitter_tags['twitter:app:id:iphone'] = $this->get_setting('twitter_app_id_ipad_handle');
249
+ $twitter_tags['twitter:app:url:iphone'] = $this->get_setting('twitter_app_url_ipad_handle');
250
+ $twitter_tags['twitter:app:name:googleplay'] = $this->get_setting('twitter_app_name_googleplay_handle');
251
+ $twitter_tags['twitter:app:id:googleplay'] = $this->get_setting('twitter_app_id_googleplay_handle');
252
+ $twitter_tags['twitter:app:url:googleplay'] = $this->get_setting('twitter_app_url_googleplay_handle');
253
+
254
+
255
+ //Output meta tags
256
+ $namespace_urls = $this->namespaces_declared ? array() : $this->get_namespace_urls();
257
+ $doctype = $this->get_setting('doctype', '');
258
+
259
+ switch ($doctype) {
260
+ case 'xhtml':
261
+ $output_formats = array('<meta%3$s name="%1$s" content="%2$s" />' => array_merge($tags, $twitter_tags));
262
+ break;
263
+ case 'html5':
264
+ $output_formats = array('<meta%3$s property="%1$s" content="%2$s">' => array_merge($tags, $twitter_tags));
265
+ break;
266
+ default:
267
+ $output_formats = array(
268
+ '<meta%3$s property="%1$s" content="%2$s" />' => $tags
269
+ , '<meta%3$s name="%1$s" content="%2$s" />' => $twitter_tags
270
+ );
271
+ break;
272
+ }
273
+
274
+ foreach ($output_formats as $html_format => $format_tags) {
275
+ foreach ($format_tags as $property => $values) {
276
+ foreach ((array)$values as $value) {
277
+ $property = su_esc_attr($property);
278
+ $value = su_esc_attr($value);
279
+ if (strlen(trim($property)) && strlen(trim($value))) {
280
+
281
+ $namespace_attr = '';
282
+ $namespace = sustr::upto($property, ':');
283
+ if (!empty($namespace_urls[$namespace])) {
284
+ $a_namespace = su_esc_attr($namespace);
285
+ $a_namespace_url = su_esc_attr($namespace_urls[$namespace]);
286
+
287
+ switch ($doctype) {
288
+ case 'xhtml':
289
+ $namespace_attr = " xmlns:$a_namespace=\"$a_namespace_url\"";
290
+ break;
291
+ case 'html5':
292
+ default:
293
+ $namespace_attr = " prefix=\"$a_namespace: $a_namespace_url\"";
294
+ break;
295
+ }
296
+ }
297
+
298
+ echo "\t";
299
+ printf($html_format, $property, $value, $namespace_attr);
300
+ echo "\n";
301
+ }
302
+ }
303
+ }
304
+ }
305
+ }
306
+
307
+ function admin_page_init() {
308
+ $this->jlsuggest_init();
309
+ }
310
+
311
+ function editor_init() {
312
+ $this->jlsuggest_init();
313
+ }
314
+
315
+ function get_admin_page_tabs() {
316
+
317
+ $postmeta_edit_tabs = $this->get_postmeta_edit_tabs(array(
318
+ array(
319
+ 'type' => 'dropdown'
320
+ , 'options' => array_merge(array('' => __('Use default', 'seo-ultimate')), $this->get_type_options())
321
+ , 'name' => 'og_type'
322
+ , 'label' => __('Type', 'seo-ultimate')
323
+ )
324
+ , array(
325
+ 'type' => 'textbox'
326
+ , 'name' => 'og_title'
327
+ , 'label' => __('Title', 'seo-ultimate')
328
+ )
329
+ , array(
330
+ 'type' => 'textbox'
331
+ , 'name' => 'og_description'
332
+ , 'label' => __('Description', 'seo-ultimate')
333
+ )
334
+ , array(
335
+ 'type' => 'jlsuggest'
336
+ , 'name' => 'og_image'
337
+ , 'label' => __('Image', 'seo-ultimate')
338
+ , 'options' => array(
339
+ 'params' => 'types=posttype_attachment&post_mime_type=image/*'
340
+ ))
341
+ ));
342
+
343
+ //Remove the Image boxes from the Media tab
344
+ //(it's obvious what the og:image of an attachment should be...)
345
+ unset($postmeta_edit_tabs['attachment']['callback'][5][3]);
346
+
347
+ return array_merge(
348
+ array(
349
+ array('title' => __('Sitewide Values', 'seo-ultimate'), 'id' => 'su-sitewide-values', 'callback' => 'global_tab')
350
+ , array('title' => __('Default Values', 'seo-ultimate'), 'id' => 'su-default-values', 'callback' => 'defaults_tab')
351
+ , array('title' => __('Settings', 'seo-ultimate'), 'id' => 'su-settings', 'callback' => 'settings_tab')
352
+ , array('title' => __('Blog Homepage', 'seo-ultimate'), 'id' => 'su-homepage', 'callback' => 'home_tab')
353
+ )
354
+ , $postmeta_edit_tabs
355
+ );
356
+ }
357
+
358
+ function global_tab() {
359
+ $this->admin_form_table_start();
360
+ $this->textbox('og_site_name', __('Site Name', 'seo-ultimate'), false, false, array(), array('placeholder' => get_bloginfo('name')));
361
+ $this->textbox('default_fb_app_id', __('Facebook App ID', 'seo-ultimate'));
362
+ $this->textbox('twitter_site_handle', __('@username of website', 'seo-ultimate'), false, false, array('help_text' => 'twitter:site', 'callout' => 'Twitter Card Tags'));
363
+ $this->textbox('twitter_site_id_handle', __('Same as twitter:site, but the user&#8217;s Twitter ID', 'seo-ultimate'), false, false, array('help_text' => 'twitter:site:id'));
364
+ $this->textbox('twitter_creator_handle', __('@username of content creator', 'seo-ultimate'), false, false, array('help_text' => 'twitter:creator'));
365
+ $this->textbox('twitter_creator_id_handle', __('Twitter user ID of content creator', 'seo-ultimate'), false, false, array('help_text' => 'twitter:creator:id'));
366
+ $this->textbox('twitter_description_handle', __('Description of content (maximum 200 characters)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:description'));
367
+ $this->textbox('twitter_title_handle', __('Title of content (maximum 70 characters)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:title'));
368
+ $this->textbox('twitter_image_src_handle', __('URL of image to use in the card. Image must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image:src'));
369
+ $this->textbox('twitter_image_width_handle', __('Width of image in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image:width'));
370
+ $this->textbox('twitter_image_height_handle', __('Height of image in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image:height'));
371
+ $this->textbox('twitter_data1_handle', __('Top customizable data field, can be a relatively short string (ie "$3.99")', 'seo-ultimate'), false, false, array('help_text' => 'twitter:data1'));
372
+ $this->textbox('twitter_label1_handle', __('Customizable label or units for the information in twitter:data1 (best practice: use all caps)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:label1'));
373
+ $this->textbox('twitter_data2_handle', __('Bottom customizable data field, can be a relatively short string (ie "Seattle, WA")', 'seo-ultimate'), false, false, array('help_text' => 'twitter:data2'));
374
+ $this->textbox('twitter_label2_handle', __('Customizable label or units for the information in twitter:data1 (best practice: use all caps)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:label2'));
375
+ $this->textbox('twitter_image0_src_handle', __('1st image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image0:src'));
376
+ $this->textbox('twitter_image1_src_handle', __('2nd image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image1:src'));
377
+ $this->textbox('twitter_image2_src_handle', __('3rd image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image2:src'));
378
+ $this->textbox('twitter_image3_src_handle', __('4th image in the gallery. Images must be less than 1MB in size.', 'seo-ultimate'), false, false, array('help_text' => 'twitter:image3:src'));
379
+ $this->textbox('twitter_player_handle', __(' HTTPS URL of player iframe', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player'));
380
+ $this->textbox('twitter_player_width_handle', __('Width of iframe in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player:width'));
381
+ $this->textbox('twitter_player_height_handle', __('Height of iframe in pixels', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player:height'));
382
+ $this->textbox('twitter_player_stream_handle', __('URL to raw video or audio stream', 'seo-ultimate'), false, false, array('help_text' => 'twitter:player:stream'));
383
+ $this->textbox('twitter_app_name_iphone_handle', __('Name of your iPhone app', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:name:iphone'));
384
+ $this->textbox('twitter_app_id_iphone_handle', __('Your app ID in the iTunes App Store (Note: NOT your bundle ID)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:id:iphone'));
385
+ $this->textbox('twitter_app_url_iphone_handle', __('Your app&#8217;s custom URL scheme (you must include "://" after your scheme name)', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:url:iphone'));
386
+ $this->textbox('twitter_app_name_ipad_handle', __('Name of your iPad optimized app', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:name:ipad'));
387
+ $this->textbox('twitter_app_id_ipad_handle', __('Your app ID in the iTunes App Store', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:id:ipad'));
388
+ $this->textbox('twitter_app_url_ipad_handle', __('Your app&#8217;s custom URL scheme', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:url:ipad'));
389
+ $this->textbox('twitter_app_name_googleplay_handle', __('Name of your Android app', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:name:googleplay'));
390
+ $this->textbox('twitter_app_id_googleplay_handle', __('Your app ID in the Google Play Store', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:id:googleplay'));
391
+ $this->textbox('twitter_app_url_googleplay_handle', __('Your app#8217;s custom URL scheme', 'seo-ultimate'), false, false, array('help_text' => 'twitter:app:url:googleplay'));
392
+ $this->admin_form_table_end();
393
+ }
394
+
395
+ function defaults_tab() {
396
+ $posttypes = get_post_types(array('public' => true), 'objects');
397
+
398
+ $this->admin_subheader(__('Default Types', 'seo-ultimate'));
399
+ $this->admin_wftable_start(array(
400
+ 'posttype' => __('Post Type', 'seo-ultimate')
401
+ , 'og' => __('Open Graph Type', 'seo-ultimate')
402
+ , 'twitter' => __('Twitter Type', 'seo-ultimate')
403
+ ));
404
+ foreach ($posttypes as $posttype) {
405
+ echo "<tr valign='middle'>\n";
406
+ echo "\t<th class='su-opengraph-posttype' scope='row'>" . esc_html($posttype->labels->name) . "</th>\n";
407
+ echo "\t<td class='su-opengraph-og'>";
408
+ $this->dropdown("default_{$posttype->name}_og_type", $this->get_type_options(), false, '%s', array('in_table' => false));
409
+ echo "</td>\n";
410
+ echo "\t<td class='su-opengraph-twitter'>";
411
+ $this->dropdown("default_{$posttype->name}_twitter_card", $this->get_twitter_type_options(), false, '%s', array('in_table' => false));
412
+ echo "</td>\n";
413
+ echo "</tr>\n";
414
+ }
415
+ $this->admin_wftable_end();
416
+
417
+ $this->admin_subheader(__('Default Image', 'seo-ultimate'));
418
+ $this->admin_form_table_start();
419
+
420
+ $this->textblock(__('In the box below, you can specify an image URL or an image from your media library to use as a default image in the event that there is no image otherwise specified for a given webpage on your site.', 'seo-ultimate'));
421
+
422
+ $this->medialib_box('default_og_image', __('Default Image', 'seo-ultimate'), 'types=posttype_attachment&post_mime_type=image/*');
423
+
424
+ $this->admin_form_table_end();
425
+ }
426
+
427
+ function settings_tab() {
428
+ $this->admin_form_table_start();
429
+ $this->checkbox('enable_og_article_author', __('Include author data for posts', 'seo-ultimate'), __('Open Graph Data', 'seo-ultimate'));
430
+ $this->radiobuttons('doctype', array(
431
+ '' => __('Use the non-validating code prescribed by Open Graph and Twitter', 'seo-ultimate')
432
+ , 'xhtml' => __('Alter the code to validate as XHTML', 'seo-ultimate')
433
+ , 'html5' => __('Alter the code to validate as HTML5', 'seo-ultimate')
434
+ ), __('HTML Validation', 'seo-ultimate'));
435
+ $this->admin_form_table_end();
436
+ }
437
+
438
+ function home_tab() {
439
+ $this->admin_form_table_start();
440
+ $this->textbox('home_og_title', __('Blog Homepage Title', 'seo-ultimate'), false, false, array(), array('placeholder' => get_bloginfo('name')));
441
+ $this->textbox('home_og_description', __('Blog Homepage Description', 'seo-ultimate'), false, false, array(), array('placeholder' => get_bloginfo('description')));
442
+ $this->medialib_box('home_og_image', __('Blog Homepage Image', 'seo-ultimate'), 'types=posttype_attachment&post_mime_type=image/*');
443
+ $this->admin_form_table_end();
444
+ }
445
+
446
+ function postmeta_fields($fields, $screen) {
447
+
448
+ $fields['opengraph'][10]['og_title'] = $this->get_postmeta_textbox('og_title', __('Title:', 'seo-ultimate'));
449
+ $fields['opengraph'][20]['og_description'] = $this->get_postmeta_textarea('og_description', __('Description:', 'seo-ultimate'));
450
+ $fields['opengraph'][30]['og_image'] = $this->get_postmeta_medialib_box('og_image', __('Image:', 'seo-ultimate'));
451
+ $fields['opengraph'][40]['og_type'] = $this->get_postmeta_dropdown('og_type', array_merge(array('' => __('Use default', 'seo-ultimate')), $this->get_type_options()), __('Open Graph Type:', 'seo-ultimate'));
452
+ $fields['opengraph'][50]['twitter_card'] = $this->get_postmeta_dropdown('twitter_card', array_merge(array('' => __('Use default', 'seo-ultimate')), $this->get_twitter_type_options()), __('Twitter Type:', 'seo-ultimate'));
453
+
454
+ return $fields;
455
+ }
456
+
457
+ function get_postmeta_jlsuggest_boxes($jls_boxes) {
458
+ $this->jlsuggest_box_post_id = suwp::get_post_id();
459
+ return parent::get_postmeta_jlsuggest_boxes($jls_boxes);
460
+ }
461
+
462
+ function get_input_element($type, $name, $value=null, $extra=false, $inputid=true) {
463
+
464
+ $name_parts = explode('_', $name);
465
+ if (isset($name_parts[1]) && is_numeric($post_id = $name_parts[1]))
466
+ $this->jlsuggest_box_post_id = $post_id;
467
+ else
468
+ $this->jlsuggest_box_post_id = false;
469
+
470
+ return parent::get_input_element($type, $name, $value, $extra, $inputid);
471
+ }
472
+
473
+ function get_jlsuggest_box($name, $value, $params='', $placeholder='') {
474
+
475
+ if (empty($value) && $this->jlsuggest_box_post_id && current_theme_supports('post-thumbnails') && $thumbnail_id = get_post_thumbnail_id($this->jlsuggest_box_post_id)) {
476
+ $selected_post = get_post($thumbnail_id);
477
+ $placeholder = sprintf(__('Featured Image: %s', 'seo-ultimate'), $selected_post->post_title);
478
+ }
479
+
480
+ return parent::get_jlsuggest_box($name, $value, $params, $placeholder);
481
+ }
482
+
483
+ function get_type_options() {
484
+ return array(
485
+ 'none' => __('None', 'seo-ultimate')
486
+ , __('Internet', 'seo-ultimate') => array(
487
+ 'article' => __('Article', 'seo-ultimate')
488
+ , 'blog' => __('Blog', 'seo-ultimate')
489
+ , 'profile' => __('Profile', 'seo-ultimate')
490
+ , 'website' => __('Website', 'seo-ultimate')
491
+ ),__('Products', 'seo-ultimate') => array(
492
+ 'book' => __('Book', 'seo-ultimate')
493
+ ),__('Music', 'seo-ultimate') => array(
494
+ 'music.album' => __('Album', 'seo-ultimate')
495
+ , 'music.playlist' => __('Playlist', 'seo-ultimate')
496
+ , 'music.radio_station' => __('Radio Station', 'seo-ultimate')
497
+ , 'music.song' => __('Song', 'seo-ultimate')
498
+ ),__('Videos', 'seo-ultimate') => array(
499
+ 'video.movie' => __('Movie', 'seo-ultimate')
500
+ , 'video.episode' => __('TV Episode', 'seo-ultimate')
501
+ , 'video.tv_show' => __('TV Show', 'seo-ultimate')
502
+ , 'video.other' => __('Video', 'seo-ultimate')
503
+ )
504
+ );
505
+ }
506
+
507
+ function get_twitter_type_options() {
508
+ return array(
509
+ 'summary' => __('Summary', 'seo-ultimate')
510
+ , 'product' => __('Product', 'seo-ultimate')
511
+ , 'photo' => __('Photo', 'seo-ultimate')
512
+ , 'summary_large_image' => __('Summary Large Image', 'seo-ultimate')
513
+ , 'gallery' => __('Gallery', 'seo-ultimate')
514
+ , 'player' => __('Player', 'seo-ultimate')
515
+ , 'app' => __('App', 'seo-ultimate')
516
+ );
517
+ }
518
+
519
+ function sanitize_twitter_handle($value) {
520
+ if (strpos($value, '/') === false) {
521
+ $handle = ltrim($value, '@');
522
+ } else {
523
+ $url_parts = explode('/', $value);
524
+ $handle = array_pop($url_parts);
525
+ }
526
+
527
+ $handle = sustr::preg_filter('a-zA-Z0-9_', $handle);
528
+ $handle = trim($handle);
529
+
530
+ if ($handle)
531
+ $handle = "@$handle";
532
+
533
+ return $handle;
534
+ }
535
+
536
+ function add_twitter_field( $contactmethods ) {
537
+ $contactmethods['twitter'] = __('Twitter Handle', 'seo-ultimate');
538
+ return $contactmethods;
539
+ }
540
+
541
+ function add_help_tabs($screen) {
542
+
543
+ $screen->add_help_tab(array(
544
+ 'id' => 'su-opengraph-overview'
545
+ , 'title' => __('Overview', 'seo-ultimate')
546
+ , 'content' => __("
547
+ <ul>
548
+ <li><strong>What it does:</strong> Open Graph Integrator makes it easy for you to convey information about your site to social networks like Facebook, Twitter, and Google+.</li>
549
+ <li><strong>Why it helps:</strong> By providing this Open Graph data, you can customize how these social networks will present your site when people share it with their followers.</li>
550
+ <li><strong>How to use it:</strong> The &#8220;Sitewide Values&#8221; tab lets you specify data that applies to your entire site. The &#8220;Default Values&#8221; tab lets you specify default data for your posts, pages, etc. The bulk editor tabs let you override those defaults on individual posts and pages. If the authors on your site fill in the &#8220;Twitter Handle&#8221; field which Open Graph Integrator adds to the <a href='profile.php'>profile editor</a>, Open Graph Integrator will communicate that information to Twitter as well.</li>
551
+ </ul>
552
+ ", 'seo-ultimate')));
553
+
554
+ }
555
+ }
556
+
557
+ }
558
  ?>
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-1.jpg ADDED
Binary file
modules/sdf-ads/sdf-ads.js CHANGED
@@ -7,7 +7,6 @@ jQuery(document).ready(function($) {
7
  $('#sdf_dashboard_widget .inside').hide();
8
  var sds_promo_blog_post = $('#sds_promo_blog_post').html();
9
  var banners_remote = ({
10
- "enabled":true,
11
  "banners": [
12
  {"banner_img":"InternalLinkBanner.jpg", "banner_link":"https://seodesignframework.leadpages.net/internal-links/"},
13
  {"banner_img":"MetaWritingBanner.jpg", "banner_link":"https://seodesignframework.leadpages.net/meta-titles-descriptions/"}
@@ -19,12 +18,14 @@ jQuery(document).ready(function($) {
19
  {"slide_cap":"<h3>What, No Control?</h3><p>Become Master of your Blog with Page-Level Controls that Liberate Designs and Crush Limitations of other Themes and Frameworks.</p>", "slide_link":"http://www.seodesignframework.com/page-level-controls/"}
20
  ],
21
  "dashboard_widget": [
22
- {"title":"Learn How to Use SEO Ultimate", "content":"<p>Get access to <a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate video training\" href=\"https://seodesignframework.leadpages.net/seo-ultimate-video-training/\">detailed video training</a> covering each module.</p><a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate video training\" href=\"https://seodesignframework.leadpages.net/seo-ultimate-video-training/\"><img src=\"" + suModulesSdfAdsSdfAdsL10n.sdf_banners_url + "SEO-VideoTraining-Banner-v3.jpg\" alt=\"SEO Ultimate video training\" /></a>"}
23
  ]
24
  })
25
 
26
- var sdf_carousel = '';
27
- if (banners_remote.enabled === true) {
 
 
28
  var shuffled_banners = shuffleArray(banners_remote.banners);
29
  var shuffled_slides = shuffleArray(banners_remote.slides);
30
  // check if it's cloud hosted banner
@@ -51,15 +52,15 @@ jQuery(document).ready(function($) {
51
  sdf_carousel = sdf_carousel + "<div class=\"item\"><div class=\"container\"><div class=\"carousel-caption\">"+ sds_promo_blog_post + "</div></div></div>";
52
  sdf_carousel = sdf_carousel + "</div><a class=\"left carousel-control\" href=\"#sdfCarousel\" data-slide=\"prev\"><span class=\"glyphicon glyphicon-chevron-left\"></span></a><a class=\"right carousel-control\" href=\"#sdfCarousel\" data-slide=\"next\"><span class=\"glyphicon glyphicon-chevron-right\"></span></a></div>";
53
 
54
- $('#sdf-promo-carousel').html(sdf_carousel).delay(500).fadeIn(400).carousel({ interval:12000 });
55
-
56
- // dashboard widget
57
- $('#sdf_dashboard_widget h3.hndle span').html(banners_remote.dashboard_widget[0].title);
58
- $('#sdf_dashboard_widget .inside').html(banners_remote.dashboard_widget[0].content);
59
- setTimeout(function(){
60
- $('#sdf_dashboard_widget .inside').fadeIn(400);
61
- },800);
62
- }
63
 
64
  });
65
 
7
  $('#sdf_dashboard_widget .inside').hide();
8
  var sds_promo_blog_post = $('#sds_promo_blog_post').html();
9
  var banners_remote = ({
 
10
  "banners": [
11
  {"banner_img":"InternalLinkBanner.jpg", "banner_link":"https://seodesignframework.leadpages.net/internal-links/"},
12
  {"banner_img":"MetaWritingBanner.jpg", "banner_link":"https://seodesignframework.leadpages.net/meta-titles-descriptions/"}
18
  {"slide_cap":"<h3>What, No Control?</h3><p>Become Master of your Blog with Page-Level Controls that Liberate Designs and Crush Limitations of other Themes and Frameworks.</p>", "slide_link":"http://www.seodesignframework.com/page-level-controls/"}
19
  ],
20
  "dashboard_widget": [
21
+ {"title":"Introducing SEO Ultimate+", "content":"<a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate+\" href=\"http://www.seoultimateplus.com\"><img src=\"" + suModulesSdfAdsSdfAdsL10n.sdf_banners_url + "SEO-Ultimate-Dashboard-Bannner-1.jpg\" alt=\"SEO Ultimate+\" /></a><p>To Get Premium Support and Exclusive New Features.<br />Upgrade to <a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate+\" href=\"http://www.seoultimateplus.com\">SEO Ultimate+</a> Today!</p>"}
22
  ]
23
  })
24
 
25
+
26
+ var promo_carousel = $('#sdf-promo-carousel');
27
+ if (promo_carousel.length > 0) {
28
+ var sdf_carousel = '';
29
  var shuffled_banners = shuffleArray(banners_remote.banners);
30
  var shuffled_slides = shuffleArray(banners_remote.slides);
31
  // check if it's cloud hosted banner
52
  sdf_carousel = sdf_carousel + "<div class=\"item\"><div class=\"container\"><div class=\"carousel-caption\">"+ sds_promo_blog_post + "</div></div></div>";
53
  sdf_carousel = sdf_carousel + "</div><a class=\"left carousel-control\" href=\"#sdfCarousel\" data-slide=\"prev\"><span class=\"glyphicon glyphicon-chevron-left\"></span></a><a class=\"right carousel-control\" href=\"#sdfCarousel\" data-slide=\"next\"><span class=\"glyphicon glyphicon-chevron-right\"></span></a></div>";
54
 
55
+ promo_carousel.html(sdf_carousel).delay(500).fadeIn(400).carousel({ interval:12000 });
56
+ }
57
+
58
+ // dashboard widget
59
+ $('#sdf_dashboard_widget h3.hndle span').html(banners_remote.dashboard_widget[0].title);
60
+ $('#sdf_dashboard_widget .inside').html(banners_remote.dashboard_widget[0].content);
61
+ setTimeout(function(){
62
+ $('#sdf_dashboard_widget .inside').fadeIn(400);
63
+ },800);
64
 
65
  });
66
 
modules/titles/titles.php CHANGED
@@ -1,489 +1,489 @@
1
- <?php
2
- /**
3
- * Title Tag Rewriter Module
4
- *
5
- * @since 0.1
6
- */
7
-
8
- if (class_exists('SU_Module')) {
9
-
10
- function su_titles_export_filter($all_settings) {
11
- unset($all_settings['titles']['taxonomy_titles']);
12
- return $all_settings;
13
- }
14
- add_filter('su_settings_export_array', 'su_titles_export_filter');
15
-
16
- class SU_Titles extends SU_Module {
17
-
18
- static function get_module_title() { return __('Title Tag Rewriter', 'seo-ultimate'); }
19
- static function get_menu_title() { return __('Title Tag Rewriter', 'seo-ultimate'); }
20
-
21
- function init() {
22
-
23
- switch ($this->get_setting('rewrite_method', 'ob')) {
24
- case 'filter':
25
- add_filter('wp_title', array(&$this, 'get_title'));
26
- break;
27
- case 'ob':
28
- default:
29
- add_action('template_redirect', array(&$this, 'before_header'), 0);
30
- add_action('wp_head', array(&$this, 'after_header'), 1000);
31
- break;
32
- }
33
-
34
- add_filter('su_postmeta_help', array(&$this, 'postmeta_help'), 10);
35
- }
36
-
37
- function get_admin_page_tabs() {
38
- return array_merge(
39
- array(
40
- array('title' => __('Default Formats', 'seo-ultimate'), 'id' => 'su-default-formats', 'callback' => 'formats_tab')
41
- , array('title' => __('Settings', 'seo-ultimate'), 'id' => 'su-settings', 'callback' => 'settings_tab')
42
- )
43
- , $this->get_meta_edit_tabs(array(
44
- 'type' => 'textbox'
45
- , 'name' => 'title'
46
- , 'term_settings_key' => 'taxonomy_titles'
47
- , 'label' => __('Title Tag', 'seo-ultimate')
48
- ))
49
- );
50
- }
51
-
52
- function formats_tab() {
53
- //echo "<table class='form-table'>\n";
54
- $this->textboxes($this->get_supported_settings(), $this->get_default_settings());
55
- //echo "</table>";
56
- }
57
-
58
- function settings_tab() {
59
- $this->admin_form_table_start();
60
- $this->checkbox('terms_ucwords', __('Convert lowercase category/tag names to title case when used in title tags.', 'seo-ultimate'), __('Title Tag Variables', 'seo-ultimate'));
61
- $this->radiobuttons('rewrite_method', array(
62
- 'ob' => __('Use output buffering &mdash; no configuration required, but slower (default)', 'seo-ultimate')
63
- , 'filter' => __('Use filtering &mdash; faster, but configuration required (see the &#8220;Settings Tab&#8221 section of the &#8220;Help&#8221; dropdown for details)', 'seo-ultimate')
64
- ), __('Rewrite Method', 'seo-ultimate'));
65
- $this->admin_form_table_end();
66
- }
67
-
68
- function get_default_settings() {
69
-
70
- //We internationalize even non-text formats (like "{post} | {blog}") to allow RTL languages to switch the order of the variables
71
- return array(
72
- 'title_home' => __('{blog}', 'seo-ultimate')
73
- , 'title_single' => __('{post} | {blog}', 'seo-ultimate')
74
- , 'title_page' => __('{page} | {blog}', 'seo-ultimate')
75
- , 'title_category' => __('{category} | {blog}', 'seo-ultimate')
76
- , 'title_tag' => __('{tag} | {blog}', 'seo-ultimate')
77
- , 'title_day' => __('Archives for {month} {day}, {year} | {blog}', 'seo-ultimate')
78
- , 'title_month' => __('Archives for {month} {year} | {blog}', 'seo-ultimate')
79
- , 'title_year' => __('Archives for {year} | {blog}', 'seo-ultimate')
80
- , 'title_author' => __('Posts by {author} | {blog}', 'seo-ultimate')
81
- , 'title_search' => __('Search Results for {query} | {blog}', 'seo-ultimate')
82
- , 'title_404' => __('404 Not Found | {blog}', 'seo-ultimate')
83
- , 'title_paged' => __('{title} - Page {num}', 'seo-ultimate')
84
- , 'terms_ucwords' => true
85
- , 'rewrite_method' => 'ob'
86
- );
87
- }
88
-
89
- function get_supported_settings() {
90
- return array(
91
- 'title_home' => __('Blog Homepage Title', 'seo-ultimate')
92
- , 'title_single' => __('Post Title Format', 'seo-ultimate')
93
- , 'title_page' => __('Page Title Format', 'seo-ultimate')
94
- , 'title_category' => __('Category Title Format', 'seo-ultimate')
95
- , 'title_tag' => __('Tag Title Format', 'seo-ultimate')
96
- , 'title_day' => __('Day Archive Title Format', 'seo-ultimate')
97
- , 'title_month' => __('Month Archive Title Format', 'seo-ultimate')
98
- , 'title_year' => __('Year Archive Title Format', 'seo-ultimate')
99
- , 'title_author' => __('Author Archive Title Format', 'seo-ultimate')
100
- , 'title_search' => __('Search Title Format', 'seo-ultimate')
101
- , 'title_404' => __('404 Title Format', 'seo-ultimate')
102
- , 'title_paged' => __('Pagination Title Format', 'seo-ultimate')
103
- );
104
- }
105
-
106
- function get_title_format() {
107
- if ($key = $this->get_current_page_type())
108
- return $this->get_setting("title_$key");
109
-
110
- return false;
111
- }
112
-
113
- function get_current_page_type() {
114
- $pagetypes = $this->get_supported_settings();
115
- unset($pagetypes['title_paged']);
116
-
117
- foreach ($pagetypes as $key => $title) {
118
- $key = str_replace('title_', '', $key);
119
- if (call_user_func("is_$key")) return $key;
120
- }
121
-
122
- return false;
123
- }
124
-
125
- function should_rewrite_title() {
126
- return (!is_admin() && !is_feed());
127
- }
128
-
129
- function before_header() {
130
- if ($this->should_rewrite_title()) ob_start(array(&$this, 'change_title_tag'));
131
- }
132
-
133
- function after_header() {
134
- if ($this->should_rewrite_title()) {
135
-
136
- $handlers = ob_list_handlers();
137
- if (count($handlers) > 0 && strcasecmp($handlers[count($handlers)-1], 'SU_Titles::change_title_tag') == 0)
138
- ob_end_flush();
139
- else
140
- su_debug_log(__FILE__, __CLASS__, __FUNCTION__, __LINE__, "Other ob_list_handlers found:\n".print_r($handlers, true));
141
- }
142
- }
143
-
144
- function change_title_tag($head) {
145
-
146
- $title = $this->get_title();
147
- if (!$title) return $head;
148
- // Pre-parse the title replacement text to escape the $ ($n backreferences) when followed by a number 0-99 because of preg_replace issue
149
- $title = preg_replace('/\$(\d)/', '\\\$$1', $title);
150
- //Replace the old title with the new and return
151
- return preg_replace('/<title>[^<]*<\/title>/i', '<title>'.$title.'</title>', $head);
152
- }
153
-
154
- function get_title() {
155
-
156
- global $wp_query, $wp_locale;
157
-
158
- //Custom post/page title?
159
- if ($post_title = $this->get_postmeta('title'))
160
- return htmlspecialchars($this->get_title_paged($post_title));
161
-
162
- //Custom taxonomy title?
163
- if (suwp::is_tax()) {
164
- $tax_titles = $this->get_setting('taxonomy_titles');
165
- if ($tax_title = $tax_titles[$wp_query->get_queried_object_id()])
166
- return htmlspecialchars($this->get_title_paged($tax_title));
167
- }
168
-
169
- //Get format
170
- if (!$this->should_rewrite_title()) return '';
171
- if (!($format = $this->get_title_format())) return '';
172
-
173
- //Load post/page titles
174
- $post_id = 0;
175
- $post_title = '';
176
- $parent_title = '';
177
- if (is_singular()) {
178
- $post = $wp_query->get_queried_object();
179
- $post_title = strip_tags( apply_filters( 'single_post_title', $post->post_title ) );
180
- $post_id = $post->ID;
181
-
182
- if ($parent = $post->post_parent) {
183
- $parent = get_post($parent);
184
- $parent_title = strip_tags( apply_filters( 'single_post_title', $parent->post_title ) );
185
- }
186
- }
187
-
188
- //Load date-based archive titles
189
- if ($m = get_query_var('m')) {
190
- $year = substr($m, 0, 4);
191
- $monthnum = intval(substr($m, 4, 2));
192
- $daynum = intval(substr($m, 6, 2));
193
- } else {
194
- $year = get_query_var('year');
195
- $monthnum = get_query_var('monthnum');
196
- $daynum = get_query_var('day');
197
- }
198
- $month = $wp_locale->get_month($monthnum);
199
- $monthnum = zeroise($monthnum, 2);
200
- $day = date('jS', mktime(12,0,0,$monthnum,$daynum,$year));
201
- $daynum = zeroise($daynum, 2);
202
-
203
- //Load category titles
204
- $cat_title = $cat_titles = $cat_desc = '';
205
- if (is_category()) {
206
- $cat_title = single_cat_title('', false);
207
- $cat_desc = category_description();
208
- } elseif (count($categories = get_the_category())) {
209
- $cat_titles = su_lang_implode($categories, 'name');
210
- usort($categories, '_usort_terms_by_ID');
211
- $cat_title = $categories[0]->name;
212
- $cat_desc = category_description($categories[0]->term_id);
213
- }
214
- if (strlen($cat_title) && $this->get_setting('terms_ucwords', true))
215
- $cat_title = sustr::tclcwords($cat_title);
216
-
217
- //Load tag titles
218
- $tag_title = $tag_desc = '';
219
- if (is_tag()) {
220
- $tag_title = single_tag_title('', false);
221
- $tag_desc = tag_description();
222
-
223
- if ($this->get_setting('terms_ucwords', true))
224
- $tag_title = sustr::tclcwords($tag_title);
225
- }
226
-
227
- //Load author titles
228
- if (is_author()) {
229
- $author_obj = $wp_query->get_queried_object();
230
- } elseif (is_singular()) {
231
- global $authordata;
232
- $author_obj = $authordata;
233
- } else {
234
- $author_obj = null;
235
- }
236
- if ($author_obj)
237
- $author = array(
238
- 'username' => $author_obj->user_login
239
- , 'name' => $author_obj->display_name
240
- , 'firstname' => get_the_author_meta('first_name', $author_obj->ID)
241
- , 'lastname' => get_the_author_meta('last_name', $author_obj->ID)
242
- , 'nickname' => get_the_author_meta('nickname', $author_obj->ID)
243
- );
244
- else
245
- $author = array(
246
- 'username' => ''
247
- , 'name' => ''
248
- , 'firstname' => ''
249
- , 'lastname' => ''
250
- , 'nickname' => ''
251
- );
252
-
253
- $variables = array(
254
- '{blog}' => get_bloginfo('name')
255
- , '{tagline}' => get_bloginfo('description')
256
- , '{post}' => $post_title
257
- , '{page}' => $post_title
258
- , '{page_parent}' => $parent_title
259
- , '{category}' => $cat_title
260
- , '{categories}' => $cat_titles
261
- , '{category_description}' => $cat_desc
262
- , '{tag}' => $tag_title
263
- , '{tag_description}' => $tag_desc
264
- , '{tags}' => su_lang_implode(get_the_tags($post_id), 'name', true)
265
- , '{daynum}' => $daynum
266
- , '{day}' => $day
267
- , '{monthnum}' => $monthnum
268
- , '{month}' => $month
269
- , '{year}' => $year
270
- , '{author}' => $author['name']
271
- , '{author_name}' => $author['name']
272
- , '{author_username}' => $author['username']
273
- , '{author_firstname}' => $author['firstname']
274
- , '{author_lastname}' => $author['lastname']
275
- , '{author_nickname}' => $author['nickname']
276
- , '{query}' => su_esc_attr(get_search_query())
277
- , '{ucquery}' => su_esc_attr(ucwords(get_search_query()))
278
- , '{url_words}' => $this->get_url_words($_SERVER['REQUEST_URI'])
279
- );
280
-
281
- $title = str_replace(array_keys($variables), array_values($variables), htmlspecialchars($format));
282
-
283
- return $this->get_title_paged($title);
284
- }
285
-
286
- function get_title_paged($title) {
287
-
288
- global $wp_query, $numpages;
289
-
290
- if (is_paged() || get_query_var('page')) {
291
-
292
- if (is_paged()) {
293
- $num = absint(get_query_var('paged'));
294
- $max = absint($wp_query->max_num_pages);
295
- } else {
296
- $num = absint(get_query_var('page'));
297
-
298
- if (is_singular()) {
299
- $post = $wp_query->get_queried_object();
300
- $max = count(explode('<!--nextpage-->', $post->post_content));
301
- } else
302
- $max = '';
303
- }
304
-
305
- return str_replace(
306
- array('{title}', '{num}', '{max}'),
307
- array( $title, $num, $max ),
308
- $this->get_setting('title_paged'));
309
- } else
310
- return $title;
311
- }
312
-
313
- function get_url_words($url) {
314
-
315
- //Remove any extensions (.html, .php, etc)
316
- $url = preg_replace('|\\.[a-zA-Z]{1,4}$|', ' ', $url);
317
-
318
- //Turn slashes to >>
319
- $url = str_replace('/', ' &raquo; ', $url);
320
-
321
- //Remove word separators
322
- $url = str_replace(array('.', '/', '-'), ' ', $url);
323
-
324
- //Capitalize the first letter of every word
325
- $url = explode(' ', $url);
326
- $url = array_map('trim', $url);
327
- $url = array_map('ucwords', $url);
328
- $url = implode(' ', $url);
329
- $url = trim($url);
330
-
331
- return $url;
332
- }
333
-
334
- function postmeta_fields($fields, $screen) {
335
- $id = "_su_title";
336
- $value = su_esc_attr($this->get_postmeta('title'));
337
- $fields['serp'][10]['title'] =
338
- "<div class='form-group su textbox'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>".__('Title Tag:', 'seo-ultimate')."</label>\n<div class='col-sm-4 col-md-4'><input name='$id' id='$id' type='text' value='$value' class='form-control input-sm regular-text' tabindex='2'"
339
- . " onkeyup=\"javascript:document.getElementById('su_title_charcount').innerHTML = document.getElementById('_su_title').value.length\" />"
340
- . "</div>\n<div class='col-sm-4 col-md-4 help-text'>".sprintf(__('You&#8217;ve entered %s characters. Most search engines use up to 70.', 'seo-ultimate'), "<strong id='su_title_charcount'>".strlen($value)."</strong>")
341
- . "</div>\n</div>\n";
342
-
343
-
344
- return $fields;
345
- }
346
-
347
- function postmeta_help($help) {
348
- $help[] = __('<strong>Title Tag</strong> &mdash; The exact contents of the &lt;title&gt; tag. The title appears in visitors&#8217; title bars and in search engine result titles. If this box is left blank, then the <a href="admin.php?page=su-titles" target="_blank">default post/page titles</a> are used.', 'seo-ultimate');
349
- return $help;
350
- }
351
-
352
- function add_help_tabs($screen) {
353
-
354
- $screen->add_help_tab(array(
355
- 'id' => 'su-titles-overview'
356
- , 'title' => __('Overview', 'seo-ultimate')
357
- , 'content' => __("
358
- <ul>
359
- <li><strong>What it does:</strong> Title Tag Rewriter helps you customize the contents of your website&#8217;s <code>&lt;title&gt;</code> tags. The tag contents are displayed in web browser title bars and in search engine result pages.</li>
360
- <li><strong>Why it helps:</strong> Proper title rewriting ensures that the keywords in your post/Page titles have greater prominence for search engine spiders and users. This is an important foundation for WordPress SEO.</li>
361
- <li><strong>How to use it:</strong> Title Tag Rewriter enables recommended settings automatically, so you shouldn&#8217;t need to change anything. If you do wish to edit the rewriting formats, you can do so using the textboxes below (the &#8220;Formats & Variables&#8221; help tab includes additional information on this). You also have the option of overriding the <code>&lt;title&gt;</code> tag of an individual post/page/category/tag/etc. using the appropriate tabs below, or by using the &#8220;Title Tag&#8221; textbox that Title Tag Rewriter adds to the post/page editors.</li>
362
- </ul>
363
- ", 'seo-ultimate')));
364
-
365
- $screen->add_help_tab(array(
366
- 'id' => 'su-titles-vars'
367
- , 'title' => __('Default Formats Tab', 'seo-ultimate')
368
- , 'content' => __("
369
- <p>Various variables, surrounded in {curly brackets}, are provided for use in the title formats. All settings support the {blog} variable, which is replaced with the name of the blog, and the {tagline} variable, which is replaced with the blog tagline as set under <a href='options-general.php'>Settings &rArr; General</a>.</p>
370
-
371
- <p>Here&#8217;s information on each of the settings and its supported variables:</p>
372
-
373
- <ul>
374
- <li><strong>Blog Homepage Title</strong> &mdash; Displays on the main blog posts page.</li>
375
- <li>
376
- <p><strong>Post Title Format</strong> &mdash; Displays on single-post pages. Supports these variables:</p>
377
- <ul>
378
- <li>{post} &mdash; The post&#8217;s title.</li>
379
- <li>{category} &mdash; The title of the post category with the lowest ID number.</li>
380
- <li>{categories} &mdash; A natural-language list of the post&#8217;s categories (e.g. &#8220;Category A, Category B, and Category C&#8221;).</li>
381
- <li>{tags} &mdash; A natural-language list of the post's tags (e.g. &#8220;Tag A, Tag B, and Tag C&#8221;).</li>
382
- <li>{author} &mdash; The Display Name of the post's author.</li>
383
- <li>{author_username}, {author_firstname}, {author_lastname}, {author_nickname} &mdash; The username, first name, last name, and nickname of the post&#8217;s author, respectively, as set in his or her profile.</li>
384
- </ul>
385
- </li>
386
- <li>
387
- <p><strong>Page Title Format</strong> &mdash; Displays on WordPress Pages. Supports these variables:
388
- <ul>
389
- <li>{page} &mdash; The page&#8217;s title.</li>
390
- <li>{page_parent} &mdash; The title of the page&#8217;s parent page.</li>
391
- <li>{author} &mdash; The Display Name of the page&#8217;s author.</li>
392
- <li>{author_username}, {author_firstname}, {author_lastname}, {author_nickname} &mdash; The username, first name, last name, and nickname of the page&#8217;s author, respectively, as set in his or her profile.</li>
393
- </ul>
394
- </li>
395
- <li><strong>Category Title Format</strong> &mdash; Displays on category archives. The {category} variable is replaced with the name of the category, and {category_description} is replaced with its description.</li>
396
- <li><strong>Tag Title Format</strong> &mdash; Displays on tag archives. The {tag} variable is replaced with the name of the tag, and {tag_description} is replaced with its description.</li>
397
- <li>
398
- <p><strong>Day Archive Title Format</strong> &mdash; Displays on day archives. Supports these variables:</p>
399
- <ul>
400
- <li>{day} &mdash; The day number, with ordinal suffix, e.g. 23rd</li>
401
- <li>{daynum} &mdash; The two-digit day number, e.g. 23</li>
402
- <li>{month} &mdash; The name of the month, e.g. April</li>
403
- <li>{monthnum} &mdash; The two-digit number of the month, e.g. 04</li>
404
- <li>{year} &mdash; The year, e.g. 2009</li>
405
- </ul>
406
- </li>
407
- <li><strong>Month Archive Title Format</strong> &mdash; Displays on month archives. Supports {month}, {monthnum}, and {year}.</li>
408
- <li><strong>Year Archive Title Format</strong> &mdash; Displays on year archives. Supports the {year} variable.</li>
409
- <li><strong>Author Archive Title Format</strong> &mdash; Displays on author archives. Supports the same author variables as the Post Title Format box, i.e. {author}, {author_username}, {author_firstname}, {author_lastname}, and {author_nickname}.</li>
410
- <li><strong>Search Title Format</strong> &mdash; Displays on the result pages for WordPress&#8217;s blog search function. The {query} variable is replaced with the search query as-is. The {ucwords} variable returns the search query with the first letter of each word capitalized.</li>
411
- <li>
412
- <p><strong>404 Title Format</strong> &mdash; Displays whenever a URL doesn&#8217;t go anywhere. Supports this variable:</p>
413
- <ul>
414
- <li>{url_words} &mdash; The words used in the error-generating URL. The first letter of each word will be capitalized.</li>
415
- </ul>
416
- </li>
417
- <li>
418
- <p><strong>Pagination Title Format</strong> &mdash; Displays whenever the visitor is on a subpage (page 2, page 3, etc.) of the homepage or of an archive. Supports these variables:</p>
419
- <ul>
420
- <li>{title} &mdash; The title that would normally be displayed on page 1</li>
421
- <li>{num} &mdash; The current page number (2, 3, etc.)</li>
422
- <li>{max} &mdash; The total number of subpages available. Would usually be used like this: Page {num} of {max}</li>
423
- </ul>
424
- </li>
425
- </ul>
426
- ", 'seo-ultimate')));
427
-
428
- $screen->add_help_tab(array(
429
- 'id' => 'su-titles-settings'
430
- , 'title' => __('Settings Tab', 'seo-ultimate')
431
- , 'content' => __("
432
- <p>Here&#8217;s documentation for the options on the &#8220;Settings&#8221; tab.</p>
433
- <ul>
434
- <li><strong>Convert lowercase category/tag names to title case when used in title tags</strong> &mdash; If your Tag Title Format is set to <code>{tag} | {blog}</code> and you have a tag called &#8220;blue widgets,&#8221; your title tag would be <code>blue widgets | My WordPress Blog</code>. Enabling this setting would capitalize the words in &#8220;blue widgets&#8221; so that the title tag would be <code>Blue Widgets | My WordPress Blog</code> instead.</li>
435
- <li>
436
- <p><strong>Rewrite Method</strong> &mdash; This setting controls the method by which Title Tag Rewriter edits your site&#8217;s <code>&lt;title&gt;</code> tags.</p>
437
- <ul>
438
- <li><strong>Use output buffering</strong> &mdash; This is the &#8220;traditional&#8221; method that most SEO plugins use.
439
- With this method, SEO Ultimate will intercept your site&#8217;s <code>&lt;head&gt;</code> tag section as it&#8217;s being outputted,
440
- locate the <code>&lt;title&gt;</code> tag, edit its value, and then output the edited <code>&lt;head&gt;</code> data.
441
- The good thing about this method is that you don&#8217;t have to edit your theme in any way, as SEO Ultimate will overwrite
442
- whatever your theme puts in your <code>&lt;title&gt;</code> tag. The bad thing is that this output interception takes a few extra
443
- milliseconds to complete. If you are concerned about performance, are comfortable editing your theme&#8217;s header.php file,
444
- and will remember to edit the header.php file of any new themes you activate, you may want to try the filtering rewrite method.</li>
445
- <li>
446
- <p><strong>Use filtering</strong> &mdash; With this method, SEO Ultimate will register itself with WordPress and will replace
447
- WordPress&#8217;s <code>&lt;title&gt;</code> tag output with its own. This method can only edit the text that WordPress itself
448
- generates for the <code>&lt;title&gt;</code> tag; the filtering method can&#8217;t edit anything extra your theme may add.
449
- For this reason, you need to edit your theme to make sure it&#8217;s only pulling <code>&lt;title&gt;</code> tag data from WordPress
450
- and is not adding anything else.</p>
451
- <p>Here&#8217;s how to set up filtering:</p>
452
- <ol>
453
- <li>Go to <a href='theme-editor.php'>Appearance &rArr; Editor</a> (if you get a permissions error, you may be on a WordPress multi-site environment and may not be able to use the filtering rewrite method)</li>
454
- <li>Click &#8220;Header (header.php)&#8221;</li>
455
- <li>Look for the <code>&lt;title&gt;</code> start tag and the <code>&lt;/title&gt;</code> end tag</li>
456
- <li>Edit the text in between those tags so that it looks like this: <code>&lt;title&gt;&lt;?php wp_title(''); ?&gt;&lt;/title&gt;</code></li>
457
- <li>Click &#8220;Update File&#8221;</li>
458
- <li>Return to the &#8220;Settings&#8221; tab of Title Tag Rewriter, select &#8220;Use filtering,&#8221; and click &#8220;Save Changes&#8221;</li>
459
- </ol>
460
- </li>
461
- </ul>
462
- </li>
463
- </ul>
464
- ", 'seo-ultimate')));
465
-
466
- $screen->add_help_tab(array(
467
- 'id' => 'su-titles-faq'
468
- , 'title' => __('FAQ', 'seo-ultimate')
469
- , 'content' => __("
470
- <ul>
471
- <li><strong>Does the Title Tag Rewriter edit my post/page titles?</strong><br />No. The Title Tag Rewriter edits the <code>&lt;title&gt;</code> tags of your site, not your post/page titles.</li>
472
- <li><strong>Will rewriting the title tags of my posts change their permalinks/URLs?</strong><br />No.</li>
473
- <li><strong>What&#8217;s the difference between the &#8220;title&#8221; and the &#8220;title tag&#8221; of a post/page?</strong><br />The &#8220;title&#8221; is the title of your post or page that&#8217;s used in your site&#8217;s theme, in your site&#8217;s admin, in your site&#8217;s RSS feeds, and in your site&#8217;s <code>&lt;title&gt;</code> tags. A <code>&lt;title&gt;</code> tag is the title of a specific webpage, and it appears in your browser&#8217;s title bar and in search result listings. Title Tag Rewriter lets you edit your post&#8217;s <code>&lt;title&gt;</code> tags without editing their actual titles. This means you can edit a post&#8217;s title as it appears in search results, but not as it appears on your site.</li>
474
- </ul>
475
- ", 'seo-ultimate')));
476
-
477
- $screen->add_help_tab(array(
478
- 'id' => 'su-titles-troubleshooting'
479
- , 'title' => __('Troubleshooting', 'seo-ultimate')
480
- , 'content' => __("
481
- <ul>
482
- <li><strong>Why isn&#8217;t Title Tag Rewriter changing my <code>&lt;title&gt;</code> tags?</strong><br />Try disabling other SEO plugins, as they may be conflicting with SEO Ultimate. If you&#8217;re using the default &#8220;output buffering&#8221; rewrite method, check to make sure your theme is <a href='http://johnlamansky.com/wordpress/theme-plugin-hooks/' target='_blank'>plugin-friendly</a>. If you're using the &#8220;filtering&#8221; rewrite method, check your theme&#8217;s <code>header.php</code> file and make sure the <code>&lt;title&gt;</code> tag looks like this: <code>&lt;title&gt;&lt;?php wp_title(''); ?&gt;&lt;/title&gt;</code>.</li>
483
- </ul>
484
- ", 'seo-ultimate')));
485
- }
486
- }
487
-
488
- }
489
  ?>
1
+ <?php
2
+ /**
3
+ * Title Tag Rewriter Module
4
+ *
5
+ * @since 0.1
6
+ */
7
+
8
+ if (class_exists('SU_Module')) {
9
+
10
+ function su_titles_export_filter($all_settings) {
11
+ unset($all_settings['titles']['taxonomy_titles']);
12
+ return $all_settings;
13
+ }
14
+ add_filter('su_settings_export_array', 'su_titles_export_filter');
15
+
16
+ class SU_Titles extends SU_Module {
17
+
18
+ static function get_module_title() { return __('Title Tag Rewriter', 'seo-ultimate'); }
19
+ static function get_menu_title() { return __('Title Tag Rewriter', 'seo-ultimate'); }
20
+
21
+ function init() {
22
+
23
+ switch ($this->get_setting('rewrite_method', 'ob')) {
24
+ case 'filter':
25
+ add_filter('wp_title', array(&$this, 'get_title'));
26
+ break;
27
+ case 'ob':
28
+ default:
29
+ add_action('template_redirect', array(&$this, 'before_header'), 0);
30
+ add_action('wp_head', array(&$this, 'after_header'), 1000);
31
+ break;
32
+ }
33
+
34
+ add_filter('su_postmeta_help', array(&$this, 'postmeta_help'), 10);
35
+ }
36
+
37
+ function get_admin_page_tabs() {
38
+ return array_merge(
39
+ array(
40
+ array('title' => __('Default Formats', 'seo-ultimate'), 'id' => 'su-default-formats', 'callback' => 'formats_tab')
41
+ , array('title' => __('Settings', 'seo-ultimate'), 'id' => 'su-settings', 'callback' => 'settings_tab')
42
+ )
43
+ , $this->get_meta_edit_tabs(array(
44
+ 'type' => 'textbox'
45
+ , 'name' => 'title'
46
+ , 'term_settings_key' => 'taxonomy_titles'
47
+ , 'label' => __('Title Tag', 'seo-ultimate')
48
+ ))
49
+ );
50
+ }
51
+
52
+ function formats_tab() {
53
+ //echo "<table class='form-table'>\n";
54
+ $this->textboxes($this->get_supported_settings(), $this->get_default_settings());
55
+ //echo "</table>";
56
+ }
57
+
58
+ function settings_tab() {
59
+ $this->admin_form_table_start();
60
+ $this->checkbox('terms_ucwords', __('Convert lowercase category/tag names to title case when used in title tags.', 'seo-ultimate'), __('Title Tag Variables', 'seo-ultimate'));
61
+ $this->radiobuttons('rewrite_method', array(
62
+ 'ob' => __('Use output buffering &mdash; no configuration required, but slower (default)', 'seo-ultimate')
63
+ , 'filter' => __('Use filtering &mdash; faster, but configuration required (see the &#8220;Settings Tab&#8221 section of the &#8220;Help&#8221; dropdown for details)', 'seo-ultimate')
64
+ ), __('Rewrite Method', 'seo-ultimate'));
65
+ $this->admin_form_table_end();
66
+ }
67
+
68
+ function get_default_settings() {
69
+
70
+ //We internationalize even non-text formats (like "{post} | {blog}") to allow RTL languages to switch the order of the variables
71
+ return array(
72
+ 'title_home' => __('{blog}', 'seo-ultimate')
73
+ , 'title_single' => __('{post} | {blog}', 'seo-ultimate')
74
+ , 'title_page' => __('{page} | {blog}', 'seo-ultimate')
75
+ , 'title_category' => __('{category} | {blog}', 'seo-ultimate')
76
+ , 'title_tag' => __('{tag} | {blog}', 'seo-ultimate')
77
+ , 'title_day' => __('Archives for {month} {day}, {year} | {blog}', 'seo-ultimate')
78
+ , 'title_month' => __('Archives for {month} {year} | {blog}', 'seo-ultimate')
79
+ , 'title_year' => __('Archives for {year} | {blog}', 'seo-ultimate')
80
+ , 'title_author' => __('Posts by {author} | {blog}', 'seo-ultimate')
81
+ , 'title_search' => __('Search Results for {query} | {blog}', 'seo-ultimate')
82
+ , 'title_404' => __('404 Not Found | {blog}', 'seo-ultimate')
83
+ , 'title_paged' => __('{title} - Page {num}', 'seo-ultimate')
84
+ , 'terms_ucwords' => true
85
+ , 'rewrite_method' => 'ob'
86
+ );
87
+ }
88
+
89
+ function get_supported_settings() {
90
+ return array(
91
+ 'title_home' => __('Blog Homepage Title', 'seo-ultimate')
92
+ , 'title_single' => __('Post Title Format', 'seo-ultimate')
93
+ , 'title_page' => __('Page Title Format', 'seo-ultimate')
94
+ , 'title_category' => __('Category Title Format', 'seo-ultimate')
95
+ , 'title_tag' => __('Tag Title Format', 'seo-ultimate')
96
+ , 'title_day' => __('Day Archive Title Format', 'seo-ultimate')
97
+ , 'title_month' => __('Month Archive Title Format', 'seo-ultimate')
98
+ , 'title_year' => __('Year Archive Title Format', 'seo-ultimate')
99
+ , 'title_author' => __('Author Archive Title Format', 'seo-ultimate')
100
+ , 'title_search' => __('Search Title Format', 'seo-ultimate')
101
+ , 'title_404' => __('404 Title Format', 'seo-ultimate')
102
+ , 'title_paged' => __('Pagination Title Format', 'seo-ultimate')
103
+ );
104
+ }
105
+
106
+ function get_title_format() {
107
+ if ($key = $this->get_current_page_type())
108
+ return $this->get_setting("title_$key");
109
+
110
+ return false;
111
+ }
112
+
113
+ function get_current_page_type() {
114
+ $pagetypes = $this->get_supported_settings();
115
+ unset($pagetypes['title_paged']);
116
+
117
+ foreach ($pagetypes as $key => $title) {
118
+ $key = str_replace('title_', '', $key);
119
+ if (call_user_func("is_$key")) return $key;
120
+ }
121
+
122
+ return false;
123
+ }
124
+
125
+ function should_rewrite_title() {
126
+ return (!is_admin() && !is_feed());
127
+ }
128
+
129
+ function before_header() {
130
+ if ($this->should_rewrite_title()) ob_start(array(&$this, 'change_title_tag'));
131
+ }
132
+
133
+ function after_header() {
134
+ if ($this->should_rewrite_title()) {
135
+
136
+ $handlers = ob_list_handlers();
137
+ if (count($handlers) > 0 && strcasecmp($handlers[count($handlers)-1], 'SU_Titles::change_title_tag') == 0)
138
+ ob_end_flush();
139
+ else
140
+ su_debug_log(__FILE__, __CLASS__, __FUNCTION__, __LINE__, "Other ob_list_handlers found:\n".print_r($handlers, true));
141
+ }
142
+ }
143
+
144
+ function change_title_tag($head) {
145
+
146
+ $title = $this->get_title();
147
+ if (!$title) return $head;
148
+ // Pre-parse the title replacement text to escape the $ ($n backreferences) when followed by a number 0-99 because of preg_replace issue
149
+ $title = preg_replace('/\$(\d)/', '\\\$$1', $title);
150
+ //Replace the old title with the new and return
151
+ return preg_replace('/<title>[^<]*<\/title>/i', '<title>'.$title.'</title>', $head);
152
+ }
153
+
154
+ function get_title() {
155
+
156
+ global $wp_query, $wp_locale;
157
+
158
+ //Custom post/page title?
159
+ if ($post_title = $this->get_postmeta('title'))
160
+ return htmlspecialchars($this->get_title_paged($post_title));
161
+
162
+ //Custom taxonomy title?
163
+ if (suwp::is_tax()) {
164
+ $tax_titles = $this->get_setting('taxonomy_titles');
165
+ if ($tax_title = $tax_titles[$wp_query->get_queried_object_id()])
166
+ return htmlspecialchars($this->get_title_paged($tax_title));
167
+ }
168
+
169
+ //Get format
170
+ if (!$this->should_rewrite_title()) return '';
171
+ if (!($format = $this->get_title_format())) return '';
172
+
173
+ //Load post/page titles
174
+ $post_id = 0;
175
+ $post_title = '';
176
+ $parent_title = '';
177
+ if (is_singular()) {
178
+ $post = $wp_query->get_queried_object();
179
+ $post_title = strip_tags( apply_filters( 'single_post_title', $post->post_title, $post ) );
180
+ $post_id = $post->ID;
181
+
182
+ if ($parent = $post->post_parent) {
183
+ $parent = get_post($parent);
184
+ $parent_title = strip_tags( apply_filters( 'single_post_title', $parent->post_title, $post ) );
185
+ }
186
+ }
187
+
188
+ //Load date-based archive titles
189
+ if ($m = get_query_var('m')) {
190
+ $year = substr($m, 0, 4);
191
+ $monthnum = intval(substr($m, 4, 2));
192
+ $daynum = intval(substr($m, 6, 2));
193
+ } else {
194
+ $year = get_query_var('year');
195
+ $monthnum = get_query_var('monthnum');
196
+ $daynum = get_query_var('day');
197
+ }
198
+ $month = $wp_locale->get_month($monthnum);
199
+ $monthnum = zeroise($monthnum, 2);
200
+ $day = date('jS', mktime(12,0,0,$monthnum,$daynum,$year));
201
+ $daynum = zeroise($daynum, 2);
202
+
203
+ //Load category titles
204
+ $cat_title = $cat_titles = $cat_desc = '';
205
+ if (is_category()) {
206
+ $cat_title = single_cat_title('', false);
207
+ $cat_desc = category_description();
208
+ } elseif (count($categories = get_the_category())) {
209
+ $cat_titles = su_lang_implode($categories, 'name');
210
+ usort($categories, '_usort_terms_by_ID');
211
+ $cat_title = $categories[0]->name;
212
+ $cat_desc = category_description($categories[0]->term_id);
213
+ }
214
+ if (strlen($cat_title) && $this->get_setting('terms_ucwords', true))
215
+ $cat_title = sustr::tclcwords($cat_title);
216
+
217
+ //Load tag titles
218
+ $tag_title = $tag_desc = '';
219
+ if (is_tag()) {
220
+ $tag_title = single_tag_title('', false);
221
+ $tag_desc = tag_description();
222
+
223
+ if ($this->get_setting('terms_ucwords', true))
224
+ $tag_title = sustr::tclcwords($tag_title);
225
+ }
226
+
227
+ //Load author titles
228
+ if (is_author()) {
229
+ $author_obj = $wp_query->get_queried_object();
230
+ } elseif (is_singular()) {
231
+ global $authordata;
232
+ $author_obj = $authordata;
233
+ } else {
234
+ $author_obj = null;
235
+ }
236
+ if ($author_obj)
237
+ $author = array(
238
+ 'username' => $author_obj->user_login
239
+ , 'name' => $author_obj->display_name
240
+ , 'firstname' => get_the_author_meta('first_name', $author_obj->ID)
241
+ , 'lastname' => get_the_author_meta('last_name', $author_obj->ID)
242
+ , 'nickname' => get_the_author_meta('nickname', $author_obj->ID)
243
+ );
244
+ else
245
+ $author = array(
246
+ 'username' => ''
247
+ , 'name' => ''
248
+ , 'firstname' => ''
249
+ , 'lastname' => ''
250
+ , 'nickname' => ''
251
+ );
252
+
253
+ $variables = array(
254
+ '{blog}' => get_bloginfo('name')
255
+ , '{tagline}' => get_bloginfo('description')
256
+ , '{post}' => $post_title
257
+ , '{page}' => $post_title
258
+ , '{page_parent}' => $parent_title
259
+ , '{category}' => $cat_title
260
+ , '{categories}' => $cat_titles
261
+ , '{category_description}' => $cat_desc
262
+ , '{tag}' => $tag_title
263
+ , '{tag_description}' => $tag_desc
264
+ , '{tags}' => su_lang_implode(get_the_tags($post_id), 'name', true)
265
+ , '{daynum}' => $daynum
266
+ , '{day}' => $day
267
+ , '{monthnum}' => $monthnum
268
+ , '{month}' => $month
269
+ , '{year}' => $year
270
+ , '{author}' => $author['name']
271
+ , '{author_name}' => $author['name']
272
+ , '{author_username}' => $author['username']
273
+ , '{author_firstname}' => $author['firstname']
274
+ , '{author_lastname}' => $author['lastname']
275
+ , '{author_nickname}' => $author['nickname']
276
+ , '{query}' => su_esc_attr(get_search_query())
277
+ , '{ucquery}' => su_esc_attr(ucwords(get_search_query()))
278
+ , '{url_words}' => $this->get_url_words($_SERVER['REQUEST_URI'])
279
+ );
280
+
281
+ $title = str_replace(array_keys($variables), array_values($variables), htmlspecialchars($format));
282
+
283
+ return $this->get_title_paged($title);
284
+ }
285
+
286
+ function get_title_paged($title) {
287
+
288
+ global $wp_query, $numpages;
289
+
290
+ if (is_paged() || get_query_var('page')) {
291
+
292
+ if (is_paged()) {
293
+ $num = absint(get_query_var('paged'));
294
+ $max = absint($wp_query->max_num_pages);
295
+ } else {
296
+ $num = absint(get_query_var('page'));
297
+
298
+ if (is_singular()) {
299
+ $post = $wp_query->get_queried_object();
300
+ $max = count(explode('<!--nextpage-->', $post->post_content));
301
+ } else
302
+ $max = '';
303
+ }
304
+
305
+ return str_replace(
306
+ array('{title}', '{num}', '{max}'),
307
+ array( $title, $num, $max ),
308
+ $this->get_setting('title_paged'));
309
+ } else
310
+ return $title;
311
+ }
312
+
313
+ function get_url_words($url) {
314
+
315
+ //Remove any extensions (.html, .php, etc)
316
+ $url = preg_replace('|\\.[a-zA-Z]{1,4}$|', ' ', $url);
317
+
318
+ //Turn slashes to >>
319
+ $url = str_replace('/', ' &raquo; ', $url);
320
+
321
+ //Remove word separators
322
+ $url = str_replace(array('.', '/', '-'), ' ', $url);
323
+
324
+ //Capitalize the first letter of every word
325
+ $url = explode(' ', $url);
326
+ $url = array_map('trim', $url);
327
+ $url = array_map('ucwords', $url);
328
+ $url = implode(' ', $url);
329
+ $url = trim($url);
330
+
331
+ return $url;
332
+ }
333
+
334
+ function postmeta_fields($fields, $screen) {
335
+ $id = "_su_title";
336
+ $value = su_esc_attr($this->get_postmeta('title'));
337
+ $fields['serp'][10]['title'] =
338
+ "<div class='form-group su textbox'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>".__('Title Tag:', 'seo-ultimate')."</label>\n<div class='col-sm-4 col-md-4'><input name='$id' id='$id' type='text' value='$value' class='form-control input-sm regular-text' tabindex='2'"
339
+ . " onkeyup=\"javascript:document.getElementById('su_title_charcount').innerHTML = document.getElementById('_su_title').value.length\" />"
340
+ . "</div>\n<div class='col-sm-4 col-md-4 help-text'>".sprintf(__('You&#8217;ve entered %s characters. Most search engines use up to 70.', 'seo-ultimate'), "<strong id='su_title_charcount'>".strlen($value)."</strong>")
341
+ . "</div>\n</div>\n";
342
+
343
+
344
+ return $fields;
345
+ }
346
+
347
+ function postmeta_help($help) {
348
+ $help[] = __('<strong>Title Tag</strong> &mdash; The exact contents of the &lt;title&gt; tag. The title appears in visitors&#8217; title bars and in search engine result titles. If this box is left blank, then the <a href="admin.php?page=su-titles" target="_blank">default post/page titles</a> are used.', 'seo-ultimate');
349
+ return $help;
350
+ }
351
+
352
+ function add_help_tabs($screen) {
353
+
354
+ $screen->add_help_tab(array(
355
+ 'id' => 'su-titles-overview'
356
+ , 'title' => __('Overview', 'seo-ultimate')
357
+ , 'content' => __("
358
+ <ul>
359
+ <li><strong>What it does:</strong> Title Tag Rewriter helps you customize the contents of your website&#8217;s <code>&lt;title&gt;</code> tags. The tag contents are displayed in web browser title bars and in search engine result pages.</li>
360
+ <li><strong>Why it helps:</strong> Proper title rewriting ensures that the keywords in your post/Page titles have greater prominence for search engine spiders and users. This is an important foundation for WordPress SEO.</li>
361
+ <li><strong>How to use it:</strong> Title Tag Rewriter enables recommended settings automatically, so you shouldn&#8217;t need to change anything. If you do wish to edit the rewriting formats, you can do so using the textboxes below (the &#8220;Formats & Variables&#8221; help tab includes additional information on this). You also have the option of overriding the <code>&lt;title&gt;</code> tag of an individual post/page/category/tag/etc. using the appropriate tabs below, or by using the &#8220;Title Tag&#8221; textbox that Title Tag Rewriter adds to the post/page editors.</li>
362
+ </ul>
363
+ ", 'seo-ultimate')));
364
+
365
+ $screen->add_help_tab(array(
366
+ 'id' => 'su-titles-vars'
367
+ , 'title' => __('Default Formats Tab', 'seo-ultimate')
368
+ , 'content' => __("
369
+ <p>Various variables, surrounded in {curly brackets}, are provided for use in the title formats. All settings support the {blog} variable, which is replaced with the name of the blog, and the {tagline} variable, which is replaced with the blog tagline as set under <a href='options-general.php'>Settings &rArr; General</a>.</p>
370
+
371
+ <p>Here&#8217;s information on each of the settings and its supported variables:</p>
372
+
373
+ <ul>
374
+ <li><strong>Blog Homepage Title</strong> &mdash; Displays on the main blog posts page.</li>
375
+ <li>
376
+ <p><strong>Post Title Format</strong> &mdash; Displays on single-post pages. Supports these variables:</p>
377
+ <ul>
378
+ <li>{post} &mdash; The post&#8217;s title.</li>
379
+ <li>{category} &mdash; The title of the post category with the lowest ID number.</li>
380
+ <li>{categories} &mdash; A natural-language list of the post&#8217;s categories (e.g. &#8220;Category A, Category B, and Category C&#8221;).</li>
381
+ <li>{tags} &mdash; A natural-language list of the post's tags (e.g. &#8220;Tag A, Tag B, and Tag C&#8221;).</li>
382
+ <li>{author} &mdash; The Display Name of the post's author.</li>
383
+ <li>{author_username}, {author_firstname}, {author_lastname}, {author_nickname} &mdash; The username, first name, last name, and nickname of the post&#8217;s author, respectively, as set in his or her profile.</li>
384
+ </ul>
385
+ </li>
386
+ <li>
387
+ <p><strong>Page Title Format</strong> &mdash; Displays on WordPress Pages. Supports these variables:
388
+ <ul>
389
+ <li>{page} &mdash; The page&#8217;s title.</li>
390
+ <li>{page_parent} &mdash; The title of the page&#8217;s parent page.</li>
391
+ <li>{author} &mdash; The Display Name of the page&#8217;s author.</li>
392
+ <li>{author_username}, {author_firstname}, {author_lastname}, {author_nickname} &mdash; The username, first name, last name, and nickname of the page&#8217;s author, respectively, as set in his or her profile.</li>
393
+ </ul>
394
+ </li>
395
+ <li><strong>Category Title Format</strong> &mdash; Displays on category archives. The {category} variable is replaced with the name of the category, and {category_description} is replaced with its description.</li>
396
+ <li><strong>Tag Title Format</strong> &mdash; Displays on tag archives. The {tag} variable is replaced with the name of the tag, and {tag_description} is replaced with its description.</li>
397
+ <li>
398
+ <p><strong>Day Archive Title Format</strong> &mdash; Displays on day archives. Supports these variables:</p>
399
+ <ul>
400
+ <li>{day} &mdash; The day number, with ordinal suffix, e.g. 23rd</li>
401
+ <li>{daynum} &mdash; The two-digit day number, e.g. 23</li>
402
+ <li>{month} &mdash; The name of the month, e.g. April</li>
403
+ <li>{monthnum} &mdash; The two-digit number of the month, e.g. 04</li>
404
+ <li>{year} &mdash; The year, e.g. 2009</li>
405
+ </ul>
406
+ </li>
407
+ <li><strong>Month Archive Title Format</strong> &mdash; Displays on month archives. Supports {month}, {monthnum}, and {year}.</li>
408
+ <li><strong>Year Archive Title Format</strong> &mdash; Displays on year archives. Supports the {year} variable.</li>
409
+ <li><strong>Author Archive Title Format</strong> &mdash; Displays on author archives. Supports the same author variables as the Post Title Format box, i.e. {author}, {author_username}, {author_firstname}, {author_lastname}, and {author_nickname}.</li>
410
+ <li><strong>Search Title Format</strong> &mdash; Displays on the result pages for WordPress&#8217;s blog search function. The {query} variable is replaced with the search query as-is. The {ucwords} variable returns the search query with the first letter of each word capitalized.</li>
411
+ <li>
412
+ <p><strong>404 Title Format</strong> &mdash; Displays whenever a URL doesn&#8217;t go anywhere. Supports this variable:</p>
413
+ <ul>
414
+ <li>{url_words} &mdash; The words used in the error-generating URL. The first letter of each word will be capitalized.</li>
415
+ </ul>
416
+ </li>
417
+ <li>
418
+ <p><strong>Pagination Title Format</strong> &mdash; Displays whenever the visitor is on a subpage (page 2, page 3, etc.) of the homepage or of an archive. Supports these variables:</p>
419
+ <ul>
420
+ <li>{title} &mdash; The title that would normally be displayed on page 1</li>
421
+ <li>{num} &mdash; The current page number (2, 3, etc.)</li>
422
+ <li>{max} &mdash; The total number of subpages available. Would usually be used like this: Page {num} of {max}</li>
423
+ </ul>
424
+ </li>
425
+ </ul>
426
+ ", 'seo-ultimate')));
427
+
428
+ $screen->add_help_tab(array(
429
+ 'id' => 'su-titles-settings'
430
+ , 'title' => __('Settings Tab', 'seo-ultimate')
431
+ , 'content' => __("
432
+ <p>Here&#8217;s documentation for the options on the &#8220;Settings&#8221; tab.</p>
433
+ <ul>
434
+ <li><strong>Convert lowercase category/tag names to title case when used in title tags</strong> &mdash; If your Tag Title Format is set to <code>{tag} | {blog}</code> and you have a tag called &#8220;blue widgets,&#8221; your title tag would be <code>blue widgets | My WordPress Blog</code>. Enabling this setting would capitalize the words in &#8220;blue widgets&#8221; so that the title tag would be <code>Blue Widgets | My WordPress Blog</code> instead.</li>
435
+ <li>
436
+ <p><strong>Rewrite Method</strong> &mdash; This setting controls the method by which Title Tag Rewriter edits your site&#8217;s <code>&lt;title&gt;</code> tags.</p>
437
+ <ul>
438
+ <li><strong>Use output buffering</strong> &mdash; This is the &#8220;traditional&#8221; method that most SEO plugins use.
439
+ With this method, SEO Ultimate will intercept your site&#8217;s <code>&lt;head&gt;</code> tag section as it&#8217;s being outputted,
440
+ locate the <code>&lt;title&gt;</code> tag, edit its value, and then output the edited <code>&lt;head&gt;</code> data.
441
+ The good thing about this method is that you don&#8217;t have to edit your theme in any way, as SEO Ultimate will overwrite
442
+ whatever your theme puts in your <code>&lt;title&gt;</code> tag. The bad thing is that this output interception takes a few extra
443
+ milliseconds to complete. If you are concerned about performance, are comfortable editing your theme&#8217;s header.php file,
444
+ and will remember to edit the header.php file of any new themes you activate, you may want to try the filtering rewrite method.</li>
445
+ <li>
446
+ <p><strong>Use filtering</strong> &mdash; With this method, SEO Ultimate will register itself with WordPress and will replace
447
+ WordPress&#8217;s <code>&lt;title&gt;</code> tag output with its own. This method can only edit the text that WordPress itself
448
+ generates for the <code>&lt;title&gt;</code> tag; the filtering method can&#8217;t edit anything extra your theme may add.
449
+ For this reason, you need to edit your theme to make sure it&#8217;s only pulling <code>&lt;title&gt;</code> tag data from WordPress
450
+ and is not adding anything else.</p>
451
+ <p>Here&#8217;s how to set up filtering:</p>
452
+ <ol>
453
+ <li>Go to <a href='theme-editor.php'>Appearance &rArr; Editor</a> (if you get a permissions error, you may be on a WordPress multi-site environment and may not be able to use the filtering rewrite method)</li>
454
+ <li>Click &#8220;Header (header.php)&#8221;</li>
455
+ <li>Look for the <code>&lt;title&gt;</code> start tag and the <code>&lt;/title&gt;</code> end tag</li>
456
+ <li>Edit the text in between those tags so that it looks like this: <code>&lt;title&gt;&lt;?php wp_title(''); ?&gt;&lt;/title&gt;</code></li>
457
+ <li>Click &#8220;Update File&#8221;</li>
458
+ <li>Return to the &#8220;Settings&#8221; tab of Title Tag Rewriter, select &#8220;Use filtering,&#8221; and click &#8220;Save Changes&#8221;</li>
459
+ </ol>
460
+ </li>
461
+ </ul>
462
+ </li>
463
+ </ul>
464
+ ", 'seo-ultimate')));
465
+
466
+ $screen->add_help_tab(array(
467
+ 'id' => 'su-titles-faq'
468
+ , 'title' => __('FAQ', 'seo-ultimate')
469
+ , 'content' => __("
470
+ <ul>
471
+ <li><strong>Does the Title Tag Rewriter edit my post/page titles?</strong><br />No. The Title Tag Rewriter edits the <code>&lt;title&gt;</code> tags of your site, not your post/page titles.</li>
472
+ <li><strong>Will rewriting the title tags of my posts change their permalinks/URLs?</strong><br />No.</li>
473
+ <li><strong>What&#8217;s the difference between the &#8220;title&#8221; and the &#8220;title tag&#8221; of a post/page?</strong><br />The &#8220;title&#8221; is the title of your post or page that&#8217;s used in your site&#8217;s theme, in your site&#8217;s admin, in your site&#8217;s RSS feeds, and in your site&#8217;s <code>&lt;title&gt;</code> tags. A <code>&lt;title&gt;</code> tag is the title of a specific webpage, and it appears in your browser&#8217;s title bar and in search result listings. Title Tag Rewriter lets you edit your post&#8217;s <code>&lt;title&gt;</code> tags without editing their actual titles. This means you can edit a post&#8217;s title as it appears in search results, but not as it appears on your site.</li>
474
+ </ul>
475
+ ", 'seo-ultimate')));
476
+
477
+ $screen->add_help_tab(array(
478
+ 'id' => 'su-titles-troubleshooting'
479
+ , 'title' => __('Troubleshooting', 'seo-ultimate')
480
+ , 'content' => __("
481
+ <ul>
482
+ <li><strong>Why isn&#8217;t Title Tag Rewriter changing my <code>&lt;title&gt;</code> tags?</strong><br />Try disabling other SEO plugins, as they may be conflicting with SEO Ultimate. If you&#8217;re using the default &#8220;output buffering&#8221; rewrite method, check to make sure your theme is <a href='http://johnlamansky.com/wordpress/theme-plugin-hooks/' target='_blank'>plugin-friendly</a>. If you're using the &#8220;filtering&#8221; rewrite method, check your theme&#8217;s <code>header.php</code> file and make sure the <code>&lt;title&gt;</code> tag looks like this: <code>&lt;title&gt;&lt;?php wp_title(''); ?&gt;&lt;/title&gt;</code>.</li>
483
+ </ul>
484
+ ", 'seo-ultimate')));
485
+ }
486
+ }
487
+
488
+ }
489
  ?>
plugin/class.seo-ultimate.php CHANGED
@@ -1083,9 +1083,10 @@ class SEO_Ultimate {
1083
  //load if SDF is not active
1084
  global $pagenow;
1085
  $current = (isset($_GET['page'])) ? $_GET['page'] : '';
1086
- $pages = array( 'index.php', 'edit.php', 'post.php', 'post-new.php' );
 
1087
  $sdf_admin_pages = array('sdf','sdf-settings','sdf-silo','sdf-silo-manual-builder','sdf-header','sdf-layout','sdf-shortcode','sdf-styles','revslider','sdf-footer','seo', 'su-fofs', 'su-misc', 'su-user-code', 'su-autolinks', 'su-files', 'su-internal-link-aliases', 'su-meta-descriptions', 'su-meta-keywords', 'su-meta-robots', 'su-opengraph', 'seo-ultimate', 'su-wp-settings', 'su-titles', 'su-sds-blog');
1088
- if( in_array( $pagenow, $pages ) || in_array( $current, $sdf_admin_pages )) {
1089
  // admin styles
1090
  wp_register_style('sdf-bootstrap-admin', $this->plugin_dir_url.'plugin/sdf/bootstrap/css/bootstrap.admin.css', array(), null, 'screen');
1091
  wp_register_style('sdf-bootstrap-admin-theme', $this->plugin_dir_url.'plugin/sdf/bootstrap/css/bootstrap-theme.admin.css', array(), null, 'screen');
1083
  //load if SDF is not active
1084
  global $pagenow;
1085
  $current = (isset($_GET['page'])) ? $_GET['page'] : '';
1086
+ $post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : '';
1087
+ $post_types = array( 'page', 'portfolio', 'ads', '');
1088
  $sdf_admin_pages = array('sdf','sdf-settings','sdf-silo','sdf-silo-manual-builder','sdf-header','sdf-layout','sdf-shortcode','sdf-styles','revslider','sdf-footer','seo', 'su-fofs', 'su-misc', 'su-user-code', 'su-autolinks', 'su-files', 'su-internal-link-aliases', 'su-meta-descriptions', 'su-meta-keywords', 'su-meta-robots', 'su-opengraph', 'seo-ultimate', 'su-wp-settings', 'su-titles', 'su-sds-blog');
1089
+ if( in_array( $current, $sdf_admin_pages) || ( in_array( $pagenow, array( 'post.php', 'post-new.php' )) && in_array( $post_type, $post_types ) )) {
1090
  // admin styles
1091
  wp_register_style('sdf-bootstrap-admin', $this->plugin_dir_url.'plugin/sdf/bootstrap/css/bootstrap.admin.css', array(), null, 'screen');
1092
  wp_register_style('sdf-bootstrap-admin-theme', $this->plugin_dir_url.'plugin/sdf/bootstrap/css/bootstrap-theme.admin.css', array(), null, 'screen');
plugin/sdf/bootstrap/css/bootstrap.admin.css CHANGED
@@ -5802,230 +5802,7 @@ button.sdf-admin .close {
5802
  width: 900px;
5803
  }
5804
  }
5805
- .sdf-admin .tooltip {
5806
- position: absolute;
5807
- z-index: 1070;
5808
- display: block;
5809
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
5810
- font-size: 12px;
5811
- font-weight: normal;
5812
- line-height: 1.4;
5813
- opacity: 0;
5814
- filter: alpha(opacity=0);
5815
- }
5816
- .sdf-admin .tooltip.in {
5817
- opacity: 0.9;
5818
- filter: alpha(opacity=90);
5819
- }
5820
- .sdf-admin .tooltip.top {
5821
- margin-top: -3px;
5822
- padding: 5px 0;
5823
- }
5824
- .sdf-admin .tooltip.right {
5825
- margin-left: 3px;
5826
- padding: 0 5px;
5827
- }
5828
- .sdf-admin .tooltip.bottom {
5829
- margin-top: 3px;
5830
- padding: 5px 0;
5831
- }
5832
- .sdf-admin .tooltip.left {
5833
- margin-left: -3px;
5834
- padding: 0 5px;
5835
- }
5836
- .sdf-admin .tooltip-inner {
5837
- max-width: 200px;
5838
- padding: 3px 8px;
5839
- color: #ffffff;
5840
- text-align: center;
5841
- text-decoration: none;
5842
- background-color: #000000;
5843
- border-radius: 4px;
5844
- }
5845
- .sdf-admin .tooltip-arrow {
5846
- position: absolute;
5847
- width: 0;
5848
- height: 0;
5849
- border-color: transparent;
5850
- border-style: solid;
5851
- }
5852
- .sdf-admin .tooltip.top .tooltip-arrow {
5853
- bottom: 0;
5854
- left: 50%;
5855
- margin-left: -5px;
5856
- border-width: 5px 5px 0;
5857
- border-top-color: #000000;
5858
- }
5859
- .sdf-admin .tooltip.top-left .tooltip-arrow {
5860
- bottom: 0;
5861
- right: 5px;
5862
- margin-bottom: -5px;
5863
- border-width: 5px 5px 0;
5864
- border-top-color: #000000;
5865
- }
5866
- .sdf-admin .tooltip.top-right .tooltip-arrow {
5867
- bottom: 0;
5868
- left: 5px;
5869
- margin-bottom: -5px;
5870
- border-width: 5px 5px 0;
5871
- border-top-color: #000000;
5872
- }
5873
- .sdf-admin .tooltip.right .tooltip-arrow {
5874
- top: 50%;
5875
- left: 0;
5876
- margin-top: -5px;
5877
- border-width: 5px 5px 5px 0;
5878
- border-right-color: #000000;
5879
- }
5880
- .sdf-admin .tooltip.left .tooltip-arrow {
5881
- top: 50%;
5882
- right: 0;
5883
- margin-top: -5px;
5884
- border-width: 5px 0 5px 5px;
5885
- border-left-color: #000000;
5886
- }
5887
- .sdf-admin .tooltip.bottom .tooltip-arrow {
5888
- top: 0;
5889
- left: 50%;
5890
- margin-left: -5px;
5891
- border-width: 0 5px 5px;
5892
- border-bottom-color: #000000;
5893
- }
5894
- .sdf-admin .tooltip.bottom-left .tooltip-arrow {
5895
- top: 0;
5896
- right: 5px;
5897
- margin-top: -5px;
5898
- border-width: 0 5px 5px;
5899
- border-bottom-color: #000000;
5900
- }
5901
- .sdf-admin .tooltip.bottom-right .tooltip-arrow {
5902
- top: 0;
5903
- left: 5px;
5904
- margin-top: -5px;
5905
- border-width: 0 5px 5px;
5906
- border-bottom-color: #000000;
5907
- }
5908
- .sdf-admin .popover {
5909
- position: absolute;
5910
- top: 0;
5911
- left: 0;
5912
- z-index: 1060;
5913
- display: none;
5914
- max-width: 276px;
5915
- padding: 1px;
5916
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
5917
- font-size: 14px;
5918
- font-weight: normal;
5919
- line-height: 1.42857143;
5920
- text-align: left;
5921
- background-color: #ffffff;
5922
- background-clip: padding-box;
5923
- border: 1px solid #cccccc;
5924
- border: 1px solid rgba(0, 0, 0, 0.2);
5925
- border-radius: 6px;
5926
- -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
5927
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
5928
- white-space: normal;
5929
- }
5930
- .sdf-admin .popover.top {
5931
- margin-top: -10px;
5932
- }
5933
- .sdf-admin .popover.right {
5934
- margin-left: 10px;
5935
- }
5936
- .sdf-admin .popover.bottom {
5937
- margin-top: 10px;
5938
- }
5939
- .sdf-admin .popover.left {
5940
- margin-left: -10px;
5941
- }
5942
- .sdf-admin .popover-title {
5943
- margin: 0;
5944
- padding: 8px 14px;
5945
- font-size: 14px;
5946
- background-color: #f7f7f7;
5947
- border-bottom: 1px solid #ebebeb;
5948
- border-radius: 5px 5px 0 0;
5949
- }
5950
- .sdf-admin .popover-content {
5951
- padding: 9px 14px;
5952
- }
5953
- .sdf-admin .popover > .arrow,
5954
- .sdf-admin .popover > .arrow:after {
5955
- position: absolute;
5956
- display: block;
5957
- width: 0;
5958
- height: 0;
5959
- border-color: transparent;
5960
- border-style: solid;
5961
- }
5962
- .sdf-admin .popover > .arrow {
5963
- border-width: 11px;
5964
- }
5965
- .sdf-admin .popover > .arrow:after {
5966
- border-width: 10px;
5967
- content: "";
5968
- }
5969
- .sdf-admin .popover.top > .arrow {
5970
- left: 50%;
5971
- margin-left: -11px;
5972
- border-bottom-width: 0;
5973
- border-top-color: #999999;
5974
- border-top-color: rgba(0, 0, 0, 0.25);
5975
- bottom: -11px;
5976
- }
5977
- .sdf-admin .popover.top > .arrow:after {
5978
- content: " ";
5979
- bottom: 1px;
5980
- margin-left: -10px;
5981
- border-bottom-width: 0;
5982
- border-top-color: #ffffff;
5983
- }
5984
- .sdf-admin .popover.right > .arrow {
5985
- top: 50%;
5986
- left: -11px;
5987
- margin-top: -11px;
5988
- border-left-width: 0;
5989
- border-right-color: #999999;
5990
- border-right-color: rgba(0, 0, 0, 0.25);
5991
- }
5992
- .sdf-admin .popover.right > .arrow:after {
5993
- content: " ";
5994
- left: 1px;
5995
- bottom: -10px;
5996
- border-left-width: 0;
5997
- border-right-color: #ffffff;
5998
- }
5999
- .sdf-admin .popover.bottom > .arrow {
6000
- left: 50%;
6001
- margin-left: -11px;
6002
- border-top-width: 0;
6003
- border-bottom-color: #999999;
6004
- border-bottom-color: rgba(0, 0, 0, 0.25);
6005
- top: -11px;
6006
- }
6007
- .sdf-admin .popover.bottom > .arrow:after {
6008
- content: " ";
6009
- top: 1px;
6010
- margin-left: -10px;
6011
- border-top-width: 0;
6012
- border-bottom-color: #ffffff;
6013
- }
6014
- .sdf-admin .popover.left > .arrow {
6015
- top: 50%;
6016
- right: -11px;
6017
- margin-top: -11px;
6018
- border-right-width: 0;
6019
- border-left-color: #999999;
6020
- border-left-color: rgba(0, 0, 0, 0.25);
6021
- }
6022
- .sdf-admin .popover.left > .arrow:after {
6023
- content: " ";
6024
- right: 1px;
6025
- border-right-width: 0;
6026
- border-left-color: #ffffff;
6027
- bottom: -10px;
6028
- }
6029
  .sdf-admin .carousel {
6030
  position: relative;
6031
  }
5802
  width: 900px;
5803
  }
5804
  }
5805
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5806
  .sdf-admin .carousel {
5807
  position: relative;
5808
  }
plugin/sdf/bootstrap/js/bootstrap.js CHANGED
@@ -171,123 +171,6 @@ if (typeof jQuery === 'undefined') {
171
 
172
  }(jQuery);
173
 
174
- /* ========================================================================
175
- * Bootstrap: button.js v3.3.4
176
- * http://getbootstrap.com/javascript/#buttons
177
- * ========================================================================
178
- * Copyright 2011-2015 Twitter, Inc.
179
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
180
- * ======================================================================== */
181
-
182
-
183
- +function ($) {
184
- 'use strict';
185
-
186
- // BUTTON PUBLIC CLASS DEFINITION
187
- // ==============================
188
-
189
- var Button = function (element, options) {
190
- this.$element = $(element)
191
- this.options = $.extend({}, Button.DEFAULTS, options)
192
- this.isLoading = false
193
- }
194
-
195
- Button.VERSION = '3.3.4'
196
-
197
- Button.DEFAULTS = {
198
- loadingText: 'loading...'
199
- }
200
-
201
- Button.prototype.setState = function (state) {
202
- var d = 'disabled'
203
- var $el = this.$element
204
- var val = $el.is('input') ? 'val' : 'html'
205
- var data = $el.data()
206
-
207
- state = state + 'Text'
208
-
209
- if (data.resetText == null) $el.data('resetText', $el[val]())
210
-
211
- // push to event loop to allow forms to submit
212
- setTimeout($.proxy(function () {
213
- $el[val](data[state] == null ? this.options[state] : data[state])
214
-
215
- if (state == 'loadingText') {
216
- this.isLoading = true
217
- $el.addClass(d).attr(d, d)
218
- } else if (this.isLoading) {
219
- this.isLoading = false
220
- $el.removeClass(d).removeAttr(d)
221
- }
222
- }, this), 0)
223
- }
224
-
225
- Button.prototype.toggle = function () {
226
- var changed = true
227
- var $parent = this.$element.closest('[data-toggle="buttons"]')
228
-
229
- if ($parent.length) {
230
- var $input = this.$element.find('input')
231
- if ($input.prop('type') == 'radio') {
232
- if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
233
- else $parent.find('.active').removeClass('active')
234
- }
235
- if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
236
- } else {
237
- this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
238
- }
239
-
240
- if (changed) this.$element.toggleClass('active')
241
- }
242
-
243
-
244
- // BUTTON PLUGIN DEFINITION
245
- // ========================
246
-
247
- function Plugin(option) {
248
- return this.each(function () {
249
- var $this = $(this)
250
- var data = $this.data('bs.button')
251
- var options = typeof option == 'object' && option
252
-
253
- if (!data) $this.data('bs.button', (data = new Button(this, options)))
254
-
255
- if (option == 'toggle') data.toggle()
256
- else if (option) data.setState(option)
257
- })
258
- }
259
-
260
- var old = $.fn.button
261
-
262
- $.fn.button = Plugin
263
- $.fn.button.Constructor = Button
264
-
265
-
266
- // BUTTON NO CONFLICT
267
- // ==================
268
-
269
- $.fn.button.noConflict = function () {
270
- $.fn.button = old
271
- return this
272
- }
273
-
274
-
275
- // BUTTON DATA-API
276
- // ===============
277
-
278
- $(document)
279
- .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
280
- var $btn = $(e.target)
281
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
282
- Plugin.call($btn, 'toggle')
283
- e.preventDefault()
284
- })
285
- .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
286
- $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
287
- })
288
-
289
- }(jQuery);
290
-
291
  /* ========================================================================
292
  * Bootstrap: carousel.js v3.3.4
293
  * http://getbootstrap.com/javascript/#carousel
@@ -1240,592 +1123,6 @@ if (typeof jQuery === 'undefined') {
1240
 
1241
  }(jQuery);
1242
 
1243
- /* ========================================================================
1244
- * Bootstrap: tooltip.js v3.3.4
1245
- * http://getbootstrap.com/javascript/#tooltip
1246
- * Inspired by the original jQuery.tipsy by Jason Frame
1247
- * ========================================================================
1248
- * Copyright 2011-2015 Twitter, Inc.
1249
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1250
- * ======================================================================== */
1251
-
1252
-
1253
- +function ($) {
1254
- 'use strict';
1255
-
1256
- // TOOLTIP PUBLIC CLASS DEFINITION
1257
- // ===============================
1258
-
1259
- var Tooltip = function (element, options) {
1260
- this.type = null
1261
- this.options = null
1262
- this.enabled = null
1263
- this.timeout = null
1264
- this.hoverState = null
1265
- this.$element = null
1266
-
1267
- this.init('tooltip', element, options)
1268
- }
1269
-
1270
- Tooltip.VERSION = '3.3.4'
1271
-
1272
- Tooltip.TRANSITION_DURATION = 150
1273
-
1274
- Tooltip.DEFAULTS = {
1275
- animation: true,
1276
- placement: 'top',
1277
- selector: false,
1278
- template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1279
- trigger: 'hover focus',
1280
- title: '',
1281
- delay: 0,
1282
- html: false,
1283
- container: false,
1284
- viewport: {
1285
- selector: 'body',
1286
- padding: 0
1287
- }
1288
- }
1289
-
1290
- Tooltip.prototype.init = function (type, element, options) {
1291
- this.enabled = true
1292
- this.type = type
1293
- this.$element = $(element)
1294
- this.options = this.getOptions(options)
1295
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
1296
-
1297
- if (this.$element[0] instanceof document.constructor && !this.options.selector) {
1298
- throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
1299
- }
1300
-
1301
- var triggers = this.options.trigger.split(' ')
1302
-
1303
- for (var i = triggers.length; i--;) {
1304
- var trigger = triggers[i]
1305
-
1306
- if (trigger == 'click') {
1307
- this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1308
- } else if (trigger != 'manual') {
1309
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1310
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1311
-
1312
- this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1313
- this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1314
- }
1315
- }
1316
-
1317
- this.options.selector ?
1318
- (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1319
- this.fixTitle()
1320
- }
1321
-
1322
- Tooltip.prototype.getDefaults = function () {
1323
- return Tooltip.DEFAULTS
1324
- }
1325
-
1326
- Tooltip.prototype.getOptions = function (options) {
1327
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1328
-
1329
- if (options.delay && typeof options.delay == 'number') {
1330
- options.delay = {
1331
- show: options.delay,
1332
- hide: options.delay
1333
- }
1334
- }
1335
-
1336
- return options
1337
- }
1338
-
1339
- Tooltip.prototype.getDelegateOptions = function () {
1340
- var options = {}
1341
- var defaults = this.getDefaults()
1342
-
1343
- this._options && $.each(this._options, function (key, value) {
1344
- if (defaults[key] != value) options[key] = value
1345
- })
1346
-
1347
- return options
1348
- }
1349
-
1350
- Tooltip.prototype.enter = function (obj) {
1351
- var self = obj instanceof this.constructor ?
1352
- obj : $(obj.currentTarget).data('bs.' + this.type)
1353
-
1354
- if (self && self.$tip && self.$tip.is(':visible')) {
1355
- self.hoverState = 'in'
1356
- return
1357
- }
1358
-
1359
- if (!self) {
1360
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1361
- $(obj.currentTarget).data('bs.' + this.type, self)
1362
- }
1363
-
1364
- clearTimeout(self.timeout)
1365
-
1366
- self.hoverState = 'in'
1367
-
1368
- if (!self.options.delay || !self.options.delay.show) return self.show()
1369
-
1370
- self.timeout = setTimeout(function () {
1371
- if (self.hoverState == 'in') self.show()
1372
- }, self.options.delay.show)
1373
- }
1374
-
1375
- Tooltip.prototype.leave = function (obj) {
1376
- var self = obj instanceof this.constructor ?
1377
- obj : $(obj.currentTarget).data('bs.' + this.type)
1378
-
1379
- if (!self) {
1380
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1381
- $(obj.currentTarget).data('bs.' + this.type, self)
1382
- }
1383
-
1384
- clearTimeout(self.timeout)
1385
-
1386
- self.hoverState = 'out'
1387
-
1388
- if (!self.options.delay || !self.options.delay.hide) return self.hide()
1389
-
1390
- self.timeout = setTimeout(function () {
1391
- if (self.hoverState == 'out') self.hide()
1392
- }, self.options.delay.hide)
1393
- }
1394
-
1395
- Tooltip.prototype.show = function () {
1396
- var e = $.Event('show.bs.' + this.type)
1397
-
1398
- if (this.hasContent() && this.enabled) {
1399
- this.$element.trigger(e)
1400
-
1401
- var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1402
- if (e.isDefaultPrevented() || !inDom) return
1403
- var that = this
1404
-
1405
- var $tip = this.tip()
1406
-
1407
- var tipId = this.getUID(this.type)
1408
-
1409
- this.setContent()
1410
- $tip.attr('id', tipId)
1411
- this.$element.attr('aria-describedby', tipId)
1412
-
1413
- if (this.options.animation) $tip.addClass('fade')
1414
-
1415
- var placement = typeof this.options.placement == 'function' ?
1416
- this.options.placement.call(this, $tip[0], this.$element[0]) :
1417
- this.options.placement
1418
-
1419
- var autoToken = /\s?auto?\s?/i
1420
- var autoPlace = autoToken.test(placement)
1421
- if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1422
-
1423
- $tip
1424
- .detach()
1425
- .css({ top: 0, left: 0, display: 'block' })
1426
- .addClass(placement)
1427
- .data('bs.' + this.type, this)
1428
-
1429
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1430
-
1431
- var pos = this.getPosition()
1432
- var actualWidth = $tip[0].offsetWidth
1433
- var actualHeight = $tip[0].offsetHeight
1434
-
1435
- if (autoPlace) {
1436
- var orgPlacement = placement
1437
- var $container = this.options.container ? $(this.options.container) : this.$element.parent()
1438
- var containerDim = this.getPosition($container)
1439
-
1440
- placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
1441
- placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
1442
- placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
1443
- placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
1444
- placement
1445
-
1446
- $tip
1447
- .removeClass(orgPlacement)
1448
- .addClass(placement)
1449
- }
1450
-
1451
- var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1452
-
1453
- this.applyPlacement(calculatedOffset, placement)
1454
-
1455
- var complete = function () {
1456
- var prevHoverState = that.hoverState
1457
- that.$element.trigger('shown.bs.' + that.type)
1458
- that.hoverState = null
1459
-
1460
- if (prevHoverState == 'out') that.leave(that)
1461
- }
1462
-
1463
- $.support.transition && this.$tip.hasClass('fade') ?
1464
- $tip
1465
- .one('bsTransitionEnd', complete)
1466
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1467
- complete()
1468
- }
1469
- }
1470
-
1471
- Tooltip.prototype.applyPlacement = function (offset, placement) {
1472
- var $tip = this.tip()
1473
- var width = $tip[0].offsetWidth
1474
- var height = $tip[0].offsetHeight
1475
-
1476
- // manually read margins because getBoundingClientRect includes difference
1477
- var marginTop = parseInt($tip.css('margin-top'), 10)
1478
- var marginLeft = parseInt($tip.css('margin-left'), 10)
1479
-
1480
- // we must check for NaN for ie 8/9
1481
- if (isNaN(marginTop)) marginTop = 0
1482
- if (isNaN(marginLeft)) marginLeft = 0
1483
-
1484
- offset.top = offset.top + marginTop
1485
- offset.left = offset.left + marginLeft
1486
-
1487
- // $.fn.offset doesn't round pixel values
1488
- // so we use setOffset directly with our own function B-0
1489
- $.offset.setOffset($tip[0], $.extend({
1490
- using: function (props) {
1491
- $tip.css({
1492
- top: Math.round(props.top),
1493
- left: Math.round(props.left)
1494
- })
1495
- }
1496
- }, offset), 0)
1497
-
1498
- $tip.addClass('in')
1499
-
1500
- // check to see if placing tip in new offset caused the tip to resize itself
1501
- var actualWidth = $tip[0].offsetWidth
1502
- var actualHeight = $tip[0].offsetHeight
1503
-
1504
- if (placement == 'top' && actualHeight != height) {
1505
- offset.top = offset.top + height - actualHeight
1506
- }
1507
-
1508
- var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1509
-
1510
- if (delta.left) offset.left += delta.left
1511
- else offset.top += delta.top
1512
-
1513
- var isVertical = /top|bottom/.test(placement)
1514
- var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1515
- var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1516
-
1517
- $tip.offset(offset)
1518
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1519
- }
1520
-
1521
- Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
1522
- this.arrow()
1523
- .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1524
- .css(isVertical ? 'top' : 'left', '')
1525
- }
1526
-
1527
- Tooltip.prototype.setContent = function () {
1528
- var $tip = this.tip()
1529
- var title = this.getTitle()
1530
-
1531
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1532
- $tip.removeClass('fade in top bottom left right')
1533
- }
1534
-
1535
- Tooltip.prototype.hide = function (callback) {
1536
- var that = this
1537
- var $tip = $(this.$tip)
1538
- var e = $.Event('hide.bs.' + this.type)
1539
-
1540
- function complete() {
1541
- if (that.hoverState != 'in') $tip.detach()
1542
- that.$element
1543
- .removeAttr('aria-describedby')
1544
- .trigger('hidden.bs.' + that.type)
1545
- callback && callback()
1546
- }
1547
-
1548
- this.$element.trigger(e)
1549
-
1550
- if (e.isDefaultPrevented()) return
1551
-
1552
- $tip.removeClass('in')
1553
-
1554
- $.support.transition && $tip.hasClass('fade') ?
1555
- $tip
1556
- .one('bsTransitionEnd', complete)
1557
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1558
- complete()
1559
-
1560
- this.hoverState = null
1561
-
1562
- return this
1563
- }
1564
-
1565
- Tooltip.prototype.fixTitle = function () {
1566
- var $e = this.$element
1567
- if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1568
- $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1569
- }
1570
- }
1571
-
1572
- Tooltip.prototype.hasContent = function () {
1573
- return this.getTitle()
1574
- }
1575
-
1576
- Tooltip.prototype.getPosition = function ($element) {
1577
- $element = $element || this.$element
1578
-
1579
- var el = $element[0]
1580
- var isBody = el.tagName == 'BODY'
1581
-
1582
- var elRect = el.getBoundingClientRect()
1583
- if (elRect.width == null) {
1584
- // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1585
- elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1586
- }
1587
- var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
1588
- var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1589
- var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1590
-
1591
- return $.extend({}, elRect, scroll, outerDims, elOffset)
1592
- }
1593
-
1594
- Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1595
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1596
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1597
- placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1598
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1599
-
1600
- }
1601
-
1602
- Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1603
- var delta = { top: 0, left: 0 }
1604
- if (!this.$viewport) return delta
1605
-
1606
- var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1607
- var viewportDimensions = this.getPosition(this.$viewport)
1608
-
1609
- if (/right|left/.test(placement)) {
1610
- var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1611
- var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1612
- if (topEdgeOffset < viewportDimensions.top) { // top overflow
1613
- delta.top = viewportDimensions.top - topEdgeOffset
1614
- } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1615
- delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1616
- }
1617
- } else {
1618
- var leftEdgeOffset = pos.left - viewportPadding
1619
- var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1620
- if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1621
- delta.left = viewportDimensions.left - leftEdgeOffset
1622
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1623
- delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1624
- }
1625
- }
1626
-
1627
- return delta
1628
- }
1629
-
1630
- Tooltip.prototype.getTitle = function () {
1631
- var title
1632
- var $e = this.$element
1633
- var o = this.options
1634
-
1635
- title = $e.attr('data-original-title')
1636
- || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1637
-
1638
- return title
1639
- }
1640
-
1641
- Tooltip.prototype.getUID = function (prefix) {
1642
- do prefix += ~~(Math.random() * 1000000)
1643
- while (document.getElementById(prefix))
1644
- return prefix
1645
- }
1646
-
1647
- Tooltip.prototype.tip = function () {
1648
- return (this.$tip = this.$tip || $(this.options.template))
1649
- }
1650
-
1651
- Tooltip.prototype.arrow = function () {
1652
- return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1653
- }
1654
-
1655
- Tooltip.prototype.enable = function () {
1656
- this.enabled = true
1657
- }
1658
-
1659
- Tooltip.prototype.disable = function () {
1660
- this.enabled = false
1661
- }
1662
-
1663
- Tooltip.prototype.toggleEnabled = function () {
1664
- this.enabled = !this.enabled
1665
- }
1666
-
1667
- Tooltip.prototype.toggle = function (e) {
1668
- var self = this
1669
- if (e) {
1670
- self = $(e.currentTarget).data('bs.' + this.type)
1671
- if (!self) {
1672
- self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1673
- $(e.currentTarget).data('bs.' + this.type, self)
1674
- }
1675
- }
1676
-
1677
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1678
- }
1679
-
1680
- Tooltip.prototype.destroy = function () {
1681
- var that = this
1682
- clearTimeout(this.timeout)
1683
- this.hide(function () {
1684
- that.$element.off('.' + that.type).removeData('bs.' + that.type)
1685
- })
1686
- }
1687
-
1688
-
1689
- // TOOLTIP PLUGIN DEFINITION
1690
- // =========================
1691
-
1692
- function Plugin(option) {
1693
- return this.each(function () {
1694
- var $this = $(this)
1695
- var data = $this.data('bs.tooltip')
1696
- var options = typeof option == 'object' && option
1697
-
1698
- if (!data && /destroy|hide/.test(option)) return
1699
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1700
- if (typeof option == 'string') data[option]()
1701
- })
1702
- }
1703
-
1704
- var old = $.fn.tooltip
1705
-
1706
- $.fn.tooltip = Plugin
1707
- $.fn.tooltip.Constructor = Tooltip
1708
-
1709
-
1710
- // TOOLTIP NO CONFLICT
1711
- // ===================
1712
-
1713
- $.fn.tooltip.noConflict = function () {
1714
- $.fn.tooltip = old
1715
- return this
1716
- }
1717
-
1718
- }(jQuery);
1719
-
1720
- /* ========================================================================
1721
- * Bootstrap: popover.js v3.3.4
1722
- * http://getbootstrap.com/javascript/#popovers
1723
- * ========================================================================
1724
- * Copyright 2011-2015 Twitter, Inc.
1725
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1726
- * ======================================================================== */
1727
-
1728
-
1729
- +function ($) {
1730
- 'use strict';
1731
-
1732
- // POPOVER PUBLIC CLASS DEFINITION
1733
- // ===============================
1734
-
1735
- var Popover = function (element, options) {
1736
- this.init('popover', element, options)
1737
- }
1738
-
1739
- if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1740
-
1741
- Popover.VERSION = '3.3.4'
1742
-
1743
- Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1744
- placement: 'right',
1745
- trigger: 'click',
1746
- content: '',
1747
- template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1748
- })
1749
-
1750
-
1751
- // NOTE: POPOVER EXTENDS tooltip.js
1752
- // ================================
1753
-
1754
- Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1755
-
1756
- Popover.prototype.constructor = Popover
1757
-
1758
- Popover.prototype.getDefaults = function () {
1759
- return Popover.DEFAULTS
1760
- }
1761
-
1762
- Popover.prototype.setContent = function () {
1763
- var $tip = this.tip()
1764
- var title = this.getTitle()
1765
- var content = this.getContent()
1766
-
1767
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1768
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1769
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1770
- ](content)
1771
-
1772
- $tip.removeClass('fade top bottom left right in')
1773
-
1774
- // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1775
- // this manually by checking the contents.
1776
- if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1777
- }
1778
-
1779
- Popover.prototype.hasContent = function () {
1780
- return this.getTitle() || this.getContent()
1781
- }
1782
-
1783
- Popover.prototype.getContent = function () {
1784
- var $e = this.$element
1785
- var o = this.options
1786
-
1787
- return $e.attr('data-content')
1788
- || (typeof o.content == 'function' ?
1789
- o.content.call($e[0]) :
1790
- o.content)
1791
- }
1792
-
1793
- Popover.prototype.arrow = function () {
1794
- return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1795
- }
1796
-
1797
-
1798
- // POPOVER PLUGIN DEFINITION
1799
- // =========================
1800
-
1801
- function Plugin(option) {
1802
- return this.each(function () {
1803
- var $this = $(this)
1804
- var data = $this.data('bs.popover')
1805
- var options = typeof option == 'object' && option
1806
-
1807
- if (!data && /destroy|hide/.test(option)) return
1808
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1809
- if (typeof option == 'string') data[option]()
1810
- })
1811
- }
1812
-
1813
- var old = $.fn.popover
1814
-
1815
- $.fn.popover = Plugin
1816
- $.fn.popover.Constructor = Popover
1817
-
1818
-
1819
- // POPOVER NO CONFLICT
1820
- // ===================
1821
-
1822
- $.fn.popover.noConflict = function () {
1823
- $.fn.popover = old
1824
- return this
1825
- }
1826
-
1827
- }(jQuery);
1828
-
1829
  /* ========================================================================
1830
  * Bootstrap: scrollspy.js v3.3.4
1831
  * http://getbootstrap.com/javascript/#scrollspy
171
 
172
  }(jQuery);
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  /* ========================================================================
175
  * Bootstrap: carousel.js v3.3.4
176
  * http://getbootstrap.com/javascript/#carousel
1123
 
1124
  }(jQuery);
1125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1126
  /* ========================================================================
1127
  * Bootstrap: scrollspy.js v3.3.4
1128
  * http://getbootstrap.com/javascript/#scrollspy
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: SEO Design Solutions, JohnLamansky, djalexandar, M Rub Shuvo
3
  Tags: seo, SEO Ultimate, suite, google, yahoo, bing, search engines, admin, post, page, custom post types, categories, tags, terms, custom taxonomies, base, title, title tag, wp_title, meta, robots, noindex, nofollow, canonical, HTTP headers, 404, robots.txt, htaccess, slugs, url, anchor, more, link, excerpt, permalink, links, autolinks, code, footer, settings, redirect, 301, 302, 307, modules, uninstallable, reinstallable, downgradable, import, export, CSV, affiliate, Open Graph, og, microdata, Facebook, Twitter, Schema.org
4
  Requires at least: 3.9
5
  Tested up to: 4.2.2
6
- Stable tag: 7.6.5.5
7
 
8
  This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
9
 
@@ -11,7 +11,13 @@ This all-in-one SEO plugin gives you control over meta titles & descriptions, op
11
 
12
  = From the Creators of SEO Ultimate =
13
 
14
- If You Like SEO Ultimate, You're Going to Love Our [WordPress Theme Framework](http://www.seodesignframework.com/)
 
 
 
 
 
 
15
 
16
  = Recent Releases =
17
 
@@ -248,6 +254,11 @@ Frequently asked questions, settings help, and troubleshooting tips for SEO Ulti
248
 
249
  == Changelog ==
250
 
 
 
 
 
 
251
  = Version 7.6.5.5 (May 12, 2015) =
252
  * Bugfix: Module Enable/Disable Fix
253
  * Bugfix: Data Table classes fix
3
  Tags: seo, SEO Ultimate, suite, google, yahoo, bing, search engines, admin, post, page, custom post types, categories, tags, terms, custom taxonomies, base, title, title tag, wp_title, meta, robots, noindex, nofollow, canonical, HTTP headers, 404, robots.txt, htaccess, slugs, url, anchor, more, link, excerpt, permalink, links, autolinks, code, footer, settings, redirect, 301, 302, 307, modules, uninstallable, reinstallable, downgradable, import, export, CSV, affiliate, Open Graph, og, microdata, Facebook, Twitter, Schema.org
4
  Requires at least: 3.9
5
  Tested up to: 4.2.2
6
+ Stable tag: 7.6.5.6
7
 
8
  This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
9
 
11
 
12
  = From the Creators of SEO Ultimate =
13
 
14
+ <blockquote>
15
+ <strong>Premium Support Now Available</strong><br>
16
+ <p>The SEO Design Solutions team does not provide support for SEO Ultimate on the WordPress forums. However, dedicated one on one email support is available when you upgrade to <a title="SEO Ultimate+" href="http://www.seoultimateplus.com">SEO Ultimate+</a>. The premium version of SEO Ultimate also has exclusive new features, detailed training videos and custom revisions not available in the free version.</p>
17
+ <p>You should also check out the <a href="http://www.seodesignframework.com/" title="SEO Design Framework">SEO Design Framework</a> (a drag and drop, multipurpose WordPress theme) created as the perfect companion for SEO Ultimate+.</p>
18
+ </blockquote>
19
+
20
+ [youtube http://www.youtube.com/watch?v=F_pW_4pl6lc]
21
 
22
  = Recent Releases =
23
 
254
 
255
  == Changelog ==
256
 
257
+ = Version 7.6.5.6 (June 8, 2015) =
258
+ * Bugfix: CiviCRM Conflict Issue With SEO Ultimate Open Graph Integrator & Titles Module
259
+ * Bugfix: Excluded Bootstrap tooltips and popovers from css/js
260
+ * Bugfix: Excluded Bootstrap button js
261
+
262
  = Version 7.6.5.5 (May 12, 2015) =
263
  * Bugfix: Module Enable/Disable Fix
264
  * Bugfix: Data Table classes fix
seo-ultimate.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: SEO Ultimate
4
  Plugin URI: http://www.seodesignsolutions.com/wordpress-seo/
5
  Description: This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
6
- Version: 7.6.5.5
7
  Author: SEO Design Solutions
8
  Author URI: http://www.seodesignsolutions.com/
9
  Text Domain: seo-ultimate
@@ -12,7 +12,7 @@ Text Domain: seo-ultimate
12
  /**
13
  * The main SEO Ultimate plugin file.
14
  * @package SeoUltimate
15
- * @version 7.6.5.5
16
  * @link http://www.seodesignsolutions.com/wordpress-seo/ SEO Ultimate Homepage
17
  */
18
 
@@ -48,10 +48,10 @@ define('SU_MINIMUM_WP_VER', '3.9');
48
  //Reading plugin info from constants is faster than trying to parse it from the header above.
49
  define('SU_PLUGIN_NAME', 'SEO Ultimate');
50
  define('SU_PLUGIN_URI', 'http://www.seodesignsolutions.com/wordpress-seo/');
51
- define('SU_VERSION', '7.6.5.5');
52
  define('SU_AUTHOR', 'SEO Design Solutions');
53
  define('SU_AUTHOR_URI', 'http://www.seodesignframework.com/');
54
- define('SU_USER_AGENT', 'SeoUltimate/7.6.5.5');
55
 
56
  /********** INCLUDES **********/
57
 
3
  Plugin Name: SEO Ultimate
4
  Plugin URI: http://www.seodesignsolutions.com/wordpress-seo/
5
  Description: This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
6
+ Version: 7.6.5.6
7
  Author: SEO Design Solutions
8
  Author URI: http://www.seodesignsolutions.com/
9
  Text Domain: seo-ultimate
12
  /**
13
  * The main SEO Ultimate plugin file.
14
  * @package SeoUltimate
15
+ * @version 7.6.5.6
16
  * @link http://www.seodesignsolutions.com/wordpress-seo/ SEO Ultimate Homepage
17
  */
18
 
48
  //Reading plugin info from constants is faster than trying to parse it from the header above.
49
  define('SU_PLUGIN_NAME', 'SEO Ultimate');
50
  define('SU_PLUGIN_URI', 'http://www.seodesignsolutions.com/wordpress-seo/');
51
+ define('SU_VERSION', '7.6.5.6');
52
  define('SU_AUTHOR', 'SEO Design Solutions');
53
  define('SU_AUTHOR_URI', 'http://www.seodesignframework.com/');
54
+ define('SU_USER_AGENT', 'SeoUltimate/7.6.5.6');
55
 
56
  /********** INCLUDES **********/
57
 
translations/seo-ultimate-en_US.mo CHANGED
Binary file
translations/seo-ultimate-en_US.po CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: SEO Ultimate v7.6.5.5\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
- "POT-Creation-Date: 2015-05-12 22:50+0100\n"
8
- "PO-Revision-Date: 2015-05-12 22:50+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
@@ -1218,11 +1218,11 @@ msgstr ""
1218
 
1219
  #: modules/class.su-module.php:2801 modules/meta/meta-descriptions.php:31
1220
  #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:352
1221
- #: plugin/class.seo-ultimate.php:1874
1222
  msgid "Blog Homepage"
1223
  msgstr ""
1224
 
1225
- #: modules/class.su-module.php:2806 plugin/class.seo-ultimate.php:1950
1226
  msgid "Author"
1227
  msgstr ""
1228
 
@@ -1230,7 +1230,7 @@ msgstr ""
1230
  msgid "A Deleted User"
1231
  msgstr ""
1232
 
1233
- #: modules/class.su-module.php:2823 plugin/class.seo-ultimate.php:1980
1234
  msgid "Link Mask"
1235
  msgstr ""
1236
 
@@ -2165,7 +2165,7 @@ msgid ""
2165
  msgstr ""
2166
 
2167
  #: modules/misc/misc.php:11 modules/misc/misc.php:12
2168
- #: plugin/class.seo-ultimate.php:1584
2169
  msgid "Miscellaneous"
2170
  msgstr ""
2171
 
@@ -3466,7 +3466,7 @@ msgid "Uninstaller"
3466
  msgstr ""
3467
 
3468
  #: modules/settings/uninstall.php:18 modules/settings/uninstall.php:22
3469
- #: plugin/class.seo-ultimate.php:1412
3470
  msgid "Uninstall"
3471
  msgstr ""
3472
 
@@ -4203,98 +4203,98 @@ msgstr ""
4203
  msgid "SEO"
4204
  msgstr ""
4205
 
4206
- #: plugin/class.seo-ultimate.php:1133
4207
  msgid ""
4208
  "It looks like you made changes to the settings of this SEO Ultimate module. "
4209
  "If you leave before saving, those changes will be lost."
4210
  msgstr ""
4211
 
4212
- #: plugin/class.seo-ultimate.php:1228 plugin/class.seo-ultimate.php:1654
4213
  msgid "SEO Settings"
4214
  msgstr ""
4215
 
4216
- #: plugin/class.seo-ultimate.php:1267
4217
  #, php-format
4218
  msgid ""
4219
  "%1$s is known to cause conflicts with SEO Ultimate. Please deactivate %1$s "
4220
  "if you wish to continue using SEO Ultimate."
4221
  msgstr ""
4222
 
4223
- #: plugin/class.seo-ultimate.php:1311
4224
  msgid "new module"
4225
  msgstr ""
4226
 
4227
- #: plugin/class.seo-ultimate.php:1311
4228
  msgid "new modules"
4229
  msgstr ""
4230
 
4231
- #: plugin/class.seo-ultimate.php:1312
4232
  msgid "new feature"
4233
  msgstr ""
4234
 
4235
- #: plugin/class.seo-ultimate.php:1312
4236
  msgid "new features"
4237
  msgstr ""
4238
 
4239
- #: plugin/class.seo-ultimate.php:1313
4240
  msgid "bugfix"
4241
  msgstr ""
4242
 
4243
- #: plugin/class.seo-ultimate.php:1313
4244
  msgid "bugfixes"
4245
  msgstr ""
4246
 
4247
- #: plugin/class.seo-ultimate.php:1314
4248
  msgid "improvement"
4249
  msgstr ""
4250
 
4251
- #: plugin/class.seo-ultimate.php:1314
4252
  msgid "improvements"
4253
  msgstr ""
4254
 
4255
- #: plugin/class.seo-ultimate.php:1315
4256
  msgid "security fix"
4257
  msgstr ""
4258
 
4259
- #: plugin/class.seo-ultimate.php:1315
4260
  msgid "security fixes"
4261
  msgstr ""
4262
 
4263
- #: plugin/class.seo-ultimate.php:1316
4264
  msgid "new language pack"
4265
  msgstr ""
4266
 
4267
- #: plugin/class.seo-ultimate.php:1316
4268
  msgid "new language packs"
4269
  msgstr ""
4270
 
4271
- #: plugin/class.seo-ultimate.php:1317
4272
  msgid "language pack update"
4273
  msgstr ""
4274
 
4275
- #: plugin/class.seo-ultimate.php:1317
4276
  msgid "language pack updates"
4277
  msgstr ""
4278
 
4279
- #: plugin/class.seo-ultimate.php:1348
4280
  #, php-format
4281
  msgid "%d %s"
4282
  msgstr ""
4283
 
4284
- #: plugin/class.seo-ultimate.php:1354
4285
  #, php-format
4286
  msgid "Upgrade now to get %s. %s."
4287
  msgstr ""
4288
 
4289
- #: plugin/class.seo-ultimate.php:1356
4290
  msgid "View changelog"
4291
  msgstr ""
4292
 
4293
- #: plugin/class.seo-ultimate.php:1433
4294
  msgid "Active Modules: "
4295
  msgstr ""
4296
 
4297
- #: plugin/class.seo-ultimate.php:1500
4298
  msgid ""
4299
  "<strong>SEO Ultimate Notice:</strong> Your blog is configured to block "
4300
  "search engine spiders. To resolve this, <a href=\"options-reading.php\" "
@@ -4302,32 +4302,32 @@ msgid ""
4302
  "discourage search engines&#8221; option."
4303
  msgstr ""
4304
 
4305
- #: plugin/class.seo-ultimate.php:1581
4306
  msgid "Search Engine Listing"
4307
  msgstr ""
4308
 
4309
- #: plugin/class.seo-ultimate.php:1582
4310
  msgid "Social Networks Listing"
4311
  msgstr ""
4312
 
4313
- #: plugin/class.seo-ultimate.php:1583
4314
  msgid "Links"
4315
  msgstr ""
4316
 
4317
- #: plugin/class.seo-ultimate.php:1685
4318
  #, php-format
4319
  msgid "%1$s %2$s by %3$s"
4320
  msgstr ""
4321
 
4322
- #: plugin/class.seo-ultimate.php:1873
4323
  msgid "Home"
4324
  msgstr ""
4325
 
4326
- #: plugin/class.seo-ultimate.php:1944
4327
  msgid "Author Archives"
4328
  msgstr ""
4329
 
4330
- #: plugin/class.seo-ultimate.php:1973
4331
  msgid "Link Masks"
4332
  msgstr ""
4333
 
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: SEO Ultimate v7.6.5.6\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
+ "POT-Creation-Date: 2015-06-06 22:52+0100\n"
8
+ "PO-Revision-Date: 2015-06-06 22:52+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
1218
 
1219
  #: modules/class.su-module.php:2801 modules/meta/meta-descriptions.php:31
1220
  #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:352
1221
+ #: plugin/class.seo-ultimate.php:1875
1222
  msgid "Blog Homepage"
1223
  msgstr ""
1224
 
1225
+ #: modules/class.su-module.php:2806 plugin/class.seo-ultimate.php:1951
1226
  msgid "Author"
1227
  msgstr ""
1228
 
1230
  msgid "A Deleted User"
1231
  msgstr ""
1232
 
1233
+ #: modules/class.su-module.php:2823 plugin/class.seo-ultimate.php:1981
1234
  msgid "Link Mask"
1235
  msgstr ""
1236
 
2165
  msgstr ""
2166
 
2167
  #: modules/misc/misc.php:11 modules/misc/misc.php:12
2168
+ #: plugin/class.seo-ultimate.php:1585
2169
  msgid "Miscellaneous"
2170
  msgstr ""
2171
 
3466
  msgstr ""
3467
 
3468
  #: modules/settings/uninstall.php:18 modules/settings/uninstall.php:22
3469
+ #: plugin/class.seo-ultimate.php:1413
3470
  msgid "Uninstall"
3471
  msgstr ""
3472
 
4203
  msgid "SEO"
4204
  msgstr ""
4205
 
4206
+ #: plugin/class.seo-ultimate.php:1134
4207
  msgid ""
4208
  "It looks like you made changes to the settings of this SEO Ultimate module. "
4209
  "If you leave before saving, those changes will be lost."
4210
  msgstr ""
4211
 
4212
+ #: plugin/class.seo-ultimate.php:1229 plugin/class.seo-ultimate.php:1655
4213
  msgid "SEO Settings"
4214
  msgstr ""
4215
 
4216
+ #: plugin/class.seo-ultimate.php:1268
4217
  #, php-format
4218
  msgid ""
4219
  "%1$s is known to cause conflicts with SEO Ultimate. Please deactivate %1$s "
4220
  "if you wish to continue using SEO Ultimate."
4221
  msgstr ""
4222
 
4223
+ #: plugin/class.seo-ultimate.php:1312
4224
  msgid "new module"
4225
  msgstr ""
4226
 
4227
+ #: plugin/class.seo-ultimate.php:1312
4228
  msgid "new modules"
4229
  msgstr ""
4230
 
4231
+ #: plugin/class.seo-ultimate.php:1313
4232
  msgid "new feature"
4233
  msgstr ""
4234
 
4235
+ #: plugin/class.seo-ultimate.php:1313
4236
  msgid "new features"
4237
  msgstr ""
4238
 
4239
+ #: plugin/class.seo-ultimate.php:1314
4240
  msgid "bugfix"
4241
  msgstr ""
4242
 
4243
+ #: plugin/class.seo-ultimate.php:1314
4244
  msgid "bugfixes"
4245
  msgstr ""
4246
 
4247
+ #: plugin/class.seo-ultimate.php:1315
4248
  msgid "improvement"
4249
  msgstr ""
4250
 
4251
+ #: plugin/class.seo-ultimate.php:1315
4252
  msgid "improvements"
4253
  msgstr ""
4254
 
4255
+ #: plugin/class.seo-ultimate.php:1316
4256
  msgid "security fix"
4257
  msgstr ""
4258
 
4259
+ #: plugin/class.seo-ultimate.php:1316
4260
  msgid "security fixes"
4261
  msgstr ""
4262
 
4263
+ #: plugin/class.seo-ultimate.php:1317
4264
  msgid "new language pack"
4265
  msgstr ""
4266
 
4267
+ #: plugin/class.seo-ultimate.php:1317
4268
  msgid "new language packs"
4269
  msgstr ""
4270
 
4271
+ #: plugin/class.seo-ultimate.php:1318
4272
  msgid "language pack update"
4273
  msgstr ""
4274
 
4275
+ #: plugin/class.seo-ultimate.php:1318
4276
  msgid "language pack updates"
4277
  msgstr ""
4278
 
4279
+ #: plugin/class.seo-ultimate.php:1349
4280
  #, php-format
4281
  msgid "%d %s"
4282
  msgstr ""
4283
 
4284
+ #: plugin/class.seo-ultimate.php:1355
4285
  #, php-format
4286
  msgid "Upgrade now to get %s. %s."
4287
  msgstr ""
4288
 
4289
+ #: plugin/class.seo-ultimate.php:1357
4290
  msgid "View changelog"
4291
  msgstr ""
4292
 
4293
+ #: plugin/class.seo-ultimate.php:1434
4294
  msgid "Active Modules: "
4295
  msgstr ""
4296
 
4297
+ #: plugin/class.seo-ultimate.php:1501
4298
  msgid ""
4299
  "<strong>SEO Ultimate Notice:</strong> Your blog is configured to block "
4300
  "search engine spiders. To resolve this, <a href=\"options-reading.php\" "
4302
  "discourage search engines&#8221; option."
4303
  msgstr ""
4304
 
4305
+ #: plugin/class.seo-ultimate.php:1582
4306
  msgid "Search Engine Listing"
4307
  msgstr ""
4308
 
4309
+ #: plugin/class.seo-ultimate.php:1583
4310
  msgid "Social Networks Listing"
4311
  msgstr ""
4312
 
4313
+ #: plugin/class.seo-ultimate.php:1584
4314
  msgid "Links"
4315
  msgstr ""
4316
 
4317
+ #: plugin/class.seo-ultimate.php:1686
4318
  #, php-format
4319
  msgid "%1$s %2$s by %3$s"
4320
  msgstr ""
4321
 
4322
+ #: plugin/class.seo-ultimate.php:1874
4323
  msgid "Home"
4324
  msgstr ""
4325
 
4326
+ #: plugin/class.seo-ultimate.php:1945
4327
  msgid "Author Archives"
4328
  msgstr ""
4329
 
4330
+ #: plugin/class.seo-ultimate.php:1974
4331
  msgid "Link Masks"
4332
  msgstr ""
4333
 
translations/seo-ultimate.pot CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: SEO Ultimate v7.6.5.5\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
- "POT-Creation-Date: 2015-05-12 22:50+0100\n"
8
- "PO-Revision-Date: 2015-05-12 22:50+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
@@ -1218,11 +1218,11 @@ msgstr ""
1218
 
1219
  #: modules/class.su-module.php:2801 modules/meta/meta-descriptions.php:31
1220
  #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:352
1221
- #: plugin/class.seo-ultimate.php:1874
1222
  msgid "Blog Homepage"
1223
  msgstr ""
1224
 
1225
- #: modules/class.su-module.php:2806 plugin/class.seo-ultimate.php:1950
1226
  msgid "Author"
1227
  msgstr ""
1228
 
@@ -1230,7 +1230,7 @@ msgstr ""
1230
  msgid "A Deleted User"
1231
  msgstr ""
1232
 
1233
- #: modules/class.su-module.php:2823 plugin/class.seo-ultimate.php:1980
1234
  msgid "Link Mask"
1235
  msgstr ""
1236
 
@@ -2165,7 +2165,7 @@ msgid ""
2165
  msgstr ""
2166
 
2167
  #: modules/misc/misc.php:11 modules/misc/misc.php:12
2168
- #: plugin/class.seo-ultimate.php:1584
2169
  msgid "Miscellaneous"
2170
  msgstr ""
2171
 
@@ -3466,7 +3466,7 @@ msgid "Uninstaller"
3466
  msgstr ""
3467
 
3468
  #: modules/settings/uninstall.php:18 modules/settings/uninstall.php:22
3469
- #: plugin/class.seo-ultimate.php:1412
3470
  msgid "Uninstall"
3471
  msgstr ""
3472
 
@@ -4203,98 +4203,98 @@ msgstr ""
4203
  msgid "SEO"
4204
  msgstr ""
4205
 
4206
- #: plugin/class.seo-ultimate.php:1133
4207
  msgid ""
4208
  "It looks like you made changes to the settings of this SEO Ultimate module. "
4209
  "If you leave before saving, those changes will be lost."
4210
  msgstr ""
4211
 
4212
- #: plugin/class.seo-ultimate.php:1228 plugin/class.seo-ultimate.php:1654
4213
  msgid "SEO Settings"
4214
  msgstr ""
4215
 
4216
- #: plugin/class.seo-ultimate.php:1267
4217
  #, php-format
4218
  msgid ""
4219
  "%1$s is known to cause conflicts with SEO Ultimate. Please deactivate %1$s "
4220
  "if you wish to continue using SEO Ultimate."
4221
  msgstr ""
4222
 
4223
- #: plugin/class.seo-ultimate.php:1311
4224
  msgid "new module"
4225
  msgstr ""
4226
 
4227
- #: plugin/class.seo-ultimate.php:1311
4228
  msgid "new modules"
4229
  msgstr ""
4230
 
4231
- #: plugin/class.seo-ultimate.php:1312
4232
  msgid "new feature"
4233
  msgstr ""
4234
 
4235
- #: plugin/class.seo-ultimate.php:1312
4236
  msgid "new features"
4237
  msgstr ""
4238
 
4239
- #: plugin/class.seo-ultimate.php:1313
4240
  msgid "bugfix"
4241
  msgstr ""
4242
 
4243
- #: plugin/class.seo-ultimate.php:1313
4244
  msgid "bugfixes"
4245
  msgstr ""
4246
 
4247
- #: plugin/class.seo-ultimate.php:1314
4248
  msgid "improvement"
4249
  msgstr ""
4250
 
4251
- #: plugin/class.seo-ultimate.php:1314
4252
  msgid "improvements"
4253
  msgstr ""
4254
 
4255
- #: plugin/class.seo-ultimate.php:1315
4256
  msgid "security fix"
4257
  msgstr ""
4258
 
4259
- #: plugin/class.seo-ultimate.php:1315
4260
  msgid "security fixes"
4261
  msgstr ""
4262
 
4263
- #: plugin/class.seo-ultimate.php:1316
4264
  msgid "new language pack"
4265
  msgstr ""
4266
 
4267
- #: plugin/class.seo-ultimate.php:1316
4268
  msgid "new language packs"
4269
  msgstr ""
4270
 
4271
- #: plugin/class.seo-ultimate.php:1317
4272
  msgid "language pack update"
4273
  msgstr ""
4274
 
4275
- #: plugin/class.seo-ultimate.php:1317
4276
  msgid "language pack updates"
4277
  msgstr ""
4278
 
4279
- #: plugin/class.seo-ultimate.php:1348
4280
  #, php-format
4281
  msgid "%d %s"
4282
  msgstr ""
4283
 
4284
- #: plugin/class.seo-ultimate.php:1354
4285
  #, php-format
4286
  msgid "Upgrade now to get %s. %s."
4287
  msgstr ""
4288
 
4289
- #: plugin/class.seo-ultimate.php:1356
4290
  msgid "View changelog"
4291
  msgstr ""
4292
 
4293
- #: plugin/class.seo-ultimate.php:1433
4294
  msgid "Active Modules: "
4295
  msgstr ""
4296
 
4297
- #: plugin/class.seo-ultimate.php:1500
4298
  msgid ""
4299
  "<strong>SEO Ultimate Notice:</strong> Your blog is configured to block "
4300
  "search engine spiders. To resolve this, <a href=\"options-reading.php\" "
@@ -4302,32 +4302,32 @@ msgid ""
4302
  "discourage search engines&#8221; option."
4303
  msgstr ""
4304
 
4305
- #: plugin/class.seo-ultimate.php:1581
4306
  msgid "Search Engine Listing"
4307
  msgstr ""
4308
 
4309
- #: plugin/class.seo-ultimate.php:1582
4310
  msgid "Social Networks Listing"
4311
  msgstr ""
4312
 
4313
- #: plugin/class.seo-ultimate.php:1583
4314
  msgid "Links"
4315
  msgstr ""
4316
 
4317
- #: plugin/class.seo-ultimate.php:1685
4318
  #, php-format
4319
  msgid "%1$s %2$s by %3$s"
4320
  msgstr ""
4321
 
4322
- #: plugin/class.seo-ultimate.php:1873
4323
  msgid "Home"
4324
  msgstr ""
4325
 
4326
- #: plugin/class.seo-ultimate.php:1944
4327
  msgid "Author Archives"
4328
  msgstr ""
4329
 
4330
- #: plugin/class.seo-ultimate.php:1973
4331
  msgid "Link Masks"
4332
  msgstr ""
4333
 
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: SEO Ultimate v7.6.5.6\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
+ "POT-Creation-Date: 2015-06-06 22:52+0100\n"
8
+ "PO-Revision-Date: 2015-06-06 22:52+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
1218
 
1219
  #: modules/class.su-module.php:2801 modules/meta/meta-descriptions.php:31
1220
  #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:352
1221
+ #: plugin/class.seo-ultimate.php:1875
1222
  msgid "Blog Homepage"
1223
  msgstr ""
1224
 
1225
+ #: modules/class.su-module.php:2806 plugin/class.seo-ultimate.php:1951
1226
  msgid "Author"
1227
  msgstr ""
1228
 
1230
  msgid "A Deleted User"
1231
  msgstr ""
1232
 
1233
+ #: modules/class.su-module.php:2823 plugin/class.seo-ultimate.php:1981
1234
  msgid "Link Mask"
1235
  msgstr ""
1236
 
2165
  msgstr ""
2166
 
2167
  #: modules/misc/misc.php:11 modules/misc/misc.php:12
2168
+ #: plugin/class.seo-ultimate.php:1585
2169
  msgid "Miscellaneous"
2170
  msgstr ""
2171
 
3466
  msgstr ""
3467
 
3468
  #: modules/settings/uninstall.php:18 modules/settings/uninstall.php:22
3469
+ #: plugin/class.seo-ultimate.php:1413
3470
  msgid "Uninstall"
3471
  msgstr ""
3472
 
4203
  msgid "SEO"
4204
  msgstr ""
4205
 
4206
+ #: plugin/class.seo-ultimate.php:1134
4207
  msgid ""
4208
  "It looks like you made changes to the settings of this SEO Ultimate module. "
4209
  "If you leave before saving, those changes will be lost."
4210
  msgstr ""
4211
 
4212
+ #: plugin/class.seo-ultimate.php:1229 plugin/class.seo-ultimate.php:1655
4213
  msgid "SEO Settings"
4214
  msgstr ""
4215
 
4216
+ #: plugin/class.seo-ultimate.php:1268
4217
  #, php-format
4218
  msgid ""
4219
  "%1$s is known to cause conflicts with SEO Ultimate. Please deactivate %1$s "
4220
  "if you wish to continue using SEO Ultimate."
4221
  msgstr ""
4222
 
4223
+ #: plugin/class.seo-ultimate.php:1312
4224
  msgid "new module"
4225
  msgstr ""
4226
 
4227
+ #: plugin/class.seo-ultimate.php:1312
4228
  msgid "new modules"
4229
  msgstr ""
4230
 
4231
+ #: plugin/class.seo-ultimate.php:1313
4232
  msgid "new feature"
4233
  msgstr ""
4234
 
4235
+ #: plugin/class.seo-ultimate.php:1313
4236
  msgid "new features"
4237
  msgstr ""
4238
 
4239
+ #: plugin/class.seo-ultimate.php:1314
4240
  msgid "bugfix"
4241
  msgstr ""
4242
 
4243
+ #: plugin/class.seo-ultimate.php:1314
4244
  msgid "bugfixes"
4245
  msgstr ""
4246
 
4247
+ #: plugin/class.seo-ultimate.php:1315
4248
  msgid "improvement"
4249
  msgstr ""
4250
 
4251
+ #: plugin/class.seo-ultimate.php:1315
4252
  msgid "improvements"
4253
  msgstr ""
4254
 
4255
+ #: plugin/class.seo-ultimate.php:1316
4256
  msgid "security fix"
4257
  msgstr ""
4258
 
4259
+ #: plugin/class.seo-ultimate.php:1316
4260
  msgid "security fixes"
4261
  msgstr ""
4262
 
4263
+ #: plugin/class.seo-ultimate.php:1317
4264
  msgid "new language pack"
4265
  msgstr ""
4266
 
4267
+ #: plugin/class.seo-ultimate.php:1317
4268
  msgid "new language packs"
4269
  msgstr ""
4270
 
4271
+ #: plugin/class.seo-ultimate.php:1318
4272
  msgid "language pack update"
4273
  msgstr ""
4274
 
4275
+ #: plugin/class.seo-ultimate.php:1318
4276
  msgid "language pack updates"
4277
  msgstr ""
4278
 
4279
+ #: plugin/class.seo-ultimate.php:1349
4280
  #, php-format
4281
  msgid "%d %s"
4282
  msgstr ""
4283
 
4284
+ #: plugin/class.seo-ultimate.php:1355
4285
  #, php-format
4286
  msgid "Upgrade now to get %s. %s."
4287
  msgstr ""
4288
 
4289
+ #: plugin/class.seo-ultimate.php:1357
4290
  msgid "View changelog"
4291
  msgstr ""
4292
 
4293
+ #: plugin/class.seo-ultimate.php:1434
4294
  msgid "Active Modules: "
4295
  msgstr ""
4296
 
4297
+ #: plugin/class.seo-ultimate.php:1501
4298
  msgid ""
4299
  "<strong>SEO Ultimate Notice:</strong> Your blog is configured to block "
4300
  "search engine spiders. To resolve this, <a href=\"options-reading.php\" "
4302
  "discourage search engines&#8221; option."
4303
  msgstr ""
4304
 
4305
+ #: plugin/class.seo-ultimate.php:1582
4306
  msgid "Search Engine Listing"
4307
  msgstr ""
4308
 
4309
+ #: plugin/class.seo-ultimate.php:1583
4310
  msgid "Social Networks Listing"
4311
  msgstr ""
4312
 
4313
+ #: plugin/class.seo-ultimate.php:1584
4314
  msgid "Links"
4315
  msgstr ""
4316
 
4317
+ #: plugin/class.seo-ultimate.php:1686
4318
  #, php-format
4319
  msgid "%1$s %2$s by %3$s"
4320
  msgstr ""
4321
 
4322
+ #: plugin/class.seo-ultimate.php:1874
4323
  msgid "Home"
4324
  msgstr ""
4325
 
4326
+ #: plugin/class.seo-ultimate.php:1945
4327
  msgid "Author Archives"
4328
  msgstr ""
4329
 
4330
+ #: plugin/class.seo-ultimate.php:1974
4331
  msgid "Link Masks"
4332
  msgstr ""
4333