Qtranslate Slug - Version 1.0

Version Description

  • works with any permalink combination and qtranslate mode.
  • new branch, the plugin has been rewritten: now the code is commented and wrapped inside a class, much code has change and the performance has been increased (use caches).
  • data system changed, no ID for slug type, then it don't needs install qtrasnlate_slug table. That means slugs now are stored on meta tables and installation creates a termmeta table with some new core functions to access/save data, based on simple term meta. Upgrade process when the plugin updates from older versions.
  • the plugin generates translated slug automatically from title in empty cases.
  • the plugin checks if the slug already exists (per each language and post_type/taxonomy), and adds a progressive number in this case. Works on ajax requests for example when new taxonomies are created in edit post page.
  • possibility to translate the base of permastructs for post_types and taxonomies, uses $wp_rewrite. New admin options page for save the base permastructs.
  • added some filters, see in other notes.
  • added plugin language textdomain (.pot file).
  • updated Language selector Widget, and some new conventions like accessible functions for templating.
  • some bug fixes.
  • some Qtranslate patches.
Download this release

Release Info

Developer carlos_a_sanz
Plugin Icon wp plugin Qtranslate Slug
Version 1.0
Comparing to
See all releases

Code changes from version 0.9 to 1.0

README.md ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Qtranslate Slug ===
2
+ Contributors: Carlos Sanz García
3
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SYC46KSLRC4Q8
4
+ Tags: qtranslate, slug, multilanguage
5
+ Requires at least: 3.3
6
+ Tested up to: 3.4
7
+ Version: 1.0
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Adds support for permalink translations and fix some QTranslate deficiencies since wordpress 3.0
12
+
13
+ == Description ==
14
+
15
+ [Qtranslate](http://wordpress.org/extend/plugins/qtranslate/) is a nice plugin but unfortunately today is **outdated**. **Qtranslate Slug** is an addon to QTranslate, which adds support for permalinks translations and fix some QTranslate deficiencies since wordpress 3.0.
16
+
17
+ **Version 1.0** has been written from scratch using OOP. The code has been structured better, the functions have been marked and commented and everything is better integrated with Wordpress API.
18
+
19
+ This plugin works with **Qtranslate** since **2.5.8**.
20
+
21
+ = What is new? =
22
+
23
+ * **works** with any permalink combination and qtranslate mode.
24
+ * new branch, the plugin has been rewritten: now the code is commented and wrapped inside a class, much code has change and the performance has been increased (use caches).
25
+ * data system changed, no ID for slug type, then it don't needs install `qtrasnlate_slug` table. That means slugs now are stored on meta tables and installation creates a termmeta table with some new *core functions* to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/). Upgrade process when the plugin updates from older versions.
26
+ * the plugin generates translated slug automatically from title in empty cases.
27
+ * the plugin checks if the slug already exists (per each language and `post_type`/`taxonomy`), and adds a progressive number in this case. Works on ajax requests for example when new taxonomies are created in edit post page.
28
+ * possibility to translate the base of permastructs for *post_types* and *taxonomies*, uses [$wp_rewrite](http://codex.wordpress.org/Class_Reference/WP_Rewrite). New admin options page for save the base permastructs.
29
+ * added some filters, see in [other notes](http://wordpress.org/extend/plugins/qtranslate-slug/other_notes/).
30
+ * added plugin language textdomain (.pot file).
31
+ * updated **Language selector Widget**, and some new conventions like accessible functions for templating.
32
+ * some bug fixes.
33
+ * some Qtranslate patches.
34
+
35
+
36
+ You can also check the [project website](http://not-only-code.github.com/qtranslate-slug/) hosted on [GitHub](http://not-only-code.github.com).
37
+ Thanks for use this plugin!
38
+
39
+ == Installation ==
40
+
41
+ **This plugins requires [Qtranslate](http://wordpress.org/extend/plugins/qtranslate/) installed previously, if not, it will not activate.**
42
+
43
+ 1. Upload `qtranslate-slug` to the `/wp-content/plugins/` directory.
44
+ 1. Activate the plugin through the 'Plugins' menu in WordPress.
45
+ 1. That's all!
46
+
47
+ = Changing base permastructs =
48
+
49
+ 1. In admin: navigate to *Settings/Slug options*.
50
+ 1. Set the base permastructs for **post types** and **taxonomies** (If you setup a base permastruct for *categories* or *tags* in *Settings/Permalinks*, these will be overwritten by the translated ones).
51
+ 1. Save settings and that's all!
52
+
53
+ == Frequently Asked Questions ==
54
+
55
+ = It works with posts and pages, but with other content type? =
56
+
57
+ This plugin allows to translate slugs of: posts, pages, custom post types, categories, tags and custom taxonomies.
58
+
59
+ = Do I have to configure anything? =
60
+
61
+ If you want to translate also the base permastructs (ex. *category*, *tag*, etc). Visit the plugin settings page in the admin *Settings/Slug options*
62
+
63
+ = How can i insert a language selector in my theme ? =
64
+
65
+ You can choose to:
66
+ * use **Qtranslate Slug Widget** in your sidebar.
67
+ * place in your template `<?php if (function_exists('qts_language_menu') ) qts_language_menu('text'); ?>`. Options are: `dropdown`, `text`, `image`, and `both`.
68
+
69
+ = Appears an error 404, what can i do? =
70
+
71
+ In the admin go to *Settings/Permalinks* or *Settings/Slug options* and save.
72
+
73
+ = I can't manage translations in Nav Menus. =
74
+
75
+ That's because language selector metabox is hidden, if you are in admin *nav menus* screen, press the button **Screen options** (on top and right) and after, check the option *Languages*. It will appear a **Language** meta box on top of the left sidebar.
76
+
77
+ == Screenshots ==
78
+
79
+ 1. Edit page for: post / page / post_type, you can see the meta box for translated slugs on top and right.
80
+ 2. Add new taxonomy page
81
+ 3. Edit taxonomy page
82
+ 4. Qtranslate Slug options page for translate base permastructs of post_types and taxonomies.
83
+
84
+ == Changelog ==
85
+
86
+ = 1.0 =
87
+ * **works** with any permalink combination and qtranslate mode.
88
+ * new branch, the plugin has been rewritten: now the code is commented and wrapped inside a class, much code has change and the performance has been increased (use caches).
89
+ * data system changed, no ID for slug type, then it don't needs install `qtrasnlate_slug` table. That means slugs now are stored on meta tables and installation creates a termmeta table with some new *core functions* to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/). Upgrade process when the plugin updates from older versions.
90
+ * the plugin generates translated slug automatically from title in empty cases.
91
+ * the plugin checks if the slug already exists (per each language and `post_type`/`taxonomy`), and adds a progressive number in this case. Works on ajax requests for example when new taxonomies are created in edit post page.
92
+ * possibility to translate the base of permastructs for *post_types* and *taxonomies*, uses [$wp_rewrite](http://codex.wordpress.org/Class_Reference/WP_Rewrite). New admin options page for save the base permastructs.
93
+ * added some filters, see in [other notes](http://wordpress.org/extend/plugins/qtranslate-slug/other_notes/).
94
+ * added plugin language textdomain (.pot file).
95
+ * updated **Language selector Widget**, and some new conventions like accessible functions for templating.
96
+ * some bug fixes.
97
+ * some Qtranslate patches.
98
+
99
+ = 0.9 =
100
+ * some wordpress qTranslate bug fixes
101
+ * adds a javascript solution for qTranslate Nav Menus
102
+
103
+ = 0.8 =
104
+ * added support por Categories
105
+ * added support por Tags
106
+ * added support por Taxonomies
107
+ * added support por Custom Post Types
108
+
109
+ = 0.7 = [Zapo](http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499)
110
+ * added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit
111
+
112
+ = 0.5 and 0.6 enhanched by Marco Del Percio =
113
+
114
+ == Upgrade Notice ==
115
+
116
+ = 1.0 =
117
+ Major version, the plugin has been rewritten. Better performance, and some enhancements.
118
+
119
+ = 0.9 =
120
+ This version fix some bugs and allow multilanguage in nav-menus.
121
+
122
+ = 0.8 =
123
+ A lot of slugs content allowed
124
+
125
+ = 0.7 =
126
+ This version allows TLD domain option for a different Qtranslate fork maded by Zappo
127
+
128
+
129
+ == Other notes ==
130
+
131
+ Plugin filters reference:
132
+
133
+ = qts_validate_post_slug =
134
+
135
+ filter to process the post slug before is saved on the database.
136
+ `args: $post (object), $slug (string), $lang (string)`
137
+
138
+ = qts_validate_term_slug =
139
+
140
+ filter to process the term slug before is saved on the database.
141
+ `args: $term (object), $slug (string), $lang (string)`
142
+
143
+ = qts_url_args =
144
+
145
+ filter to process the entire url after it has been generated.
146
+ `args: $url (string), $lang (string)`
147
+
148
+ = qts_permastruct =
149
+
150
+ filter to process the permastruct, used for change the base.
151
+ `args: $permastruct (string), $name (string)`
152
+
153
+
154
+ = Todo =
155
+
156
+ * detect Slug for each language and redirect accordingly in parse_query.
157
+ * expand qtranslate for translate attachment names and descriptions ( useful for galleries )
158
+ * translate other slugs like attachments.
159
+ * multisite: add suport as network plugin enhancing the request, some qtranslate patches.
160
+ * qtranslate integration with other plugins like Jigoshop, e-commerce, etc. Addapt **$wp_rewrite**.
README.txt CHANGED
@@ -1,48 +1,101 @@
1
  === Qtranslate Slug ===
2
  Contributors: Carlos Sanz García
3
- Donate link: none
4
  Tags: qtranslate, slug, multilanguage
5
- Requires at least: 3.0
6
- Tested up to: 3.3.2
7
- Version: 0.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- Allows to define a slug for each language and some qTranslate bug fixes
12
 
13
  == Description ==
14
 
15
- This plugin allows translated slugs in Qtranslate.
16
- You need install and activate previously Qtranslate, if not, Qtranslate Slug will not work.
17
 
18
- Tested with Qtranslate versions 2.5.8 and 2.5.9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  == Installation ==
21
 
22
- This plugins requires qTranslate installed previously, if not, it will not activate.
23
 
24
- 1. Upload `qtranslate-slug` to the `/wp-content/plugins/` directory
25
- 1. Activate the plugin through the 'Plugins' menu in WordPress
26
  1. That's all!
27
 
 
 
 
 
 
 
28
  == Frequently Asked Questions ==
29
 
30
- = It works with posts and pages, but with other content type ? =
31
 
32
  This plugin allows to translate slugs of: posts, pages, custom post types, categories, tags and custom taxonomies.
33
 
34
- = How can I insert a language selector in my theme ? =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- Place `<?php if (function_exists('qTranslateSlug_generateLanguageSelectCode') ) qTranslateSlug_generateLanguageSelectCode('text'); ?>` in your template.
37
 
38
  == Screenshots ==
39
 
40
- 1. This screen shot description corresponds to screenshot-1.(png|jpg|jpeg|gif). Note that the screenshot is taken from
41
- the directory of the stable readme.txt, so in this case, `/tags/4.3/screenshot-1.png` (or jpg, jpeg, gif)
42
- 2. This is the second screen shot
 
43
 
44
  == Changelog ==
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  = 0.9 =
47
  * some wordpress qTranslate bug fixes
48
  * adds a javascript solution for qTranslate Nav Menus
@@ -53,13 +106,16 @@ the directory of the stable readme.txt, so in this case, `/tags/4.3/screenshot-1
53
  * added support por Taxonomies
54
  * added support por Custom Post Types
55
 
56
- = 0.7 ( enhanced by Zapo (http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499) ) =
57
  * added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit
58
 
59
  = 0.5 and 0.6 enhanched by Marco Del Percio =
60
 
61
  == Upgrade Notice ==
62
 
 
 
 
63
  = 0.9 =
64
  This version fix some bugs and allow multilanguage in nav-menus.
65
 
@@ -70,14 +126,35 @@ A lot of slugs content allowed
70
  This version allows TLD domain option for a different Qtranslate fork maded by Zappo
71
 
72
 
73
- == Todo ==
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
- * admin options page for setup the taxonomies names
76
- * change the database system ( post meta ), without installing tables
77
- * generate translated slug automatically from the translated title
78
- * check if the slug is already used, and add a progressive number in this case
79
- * force the use of the translated slug if defined
80
- * force to show a page/post only at the correct URL
81
- * try to redirect from a wrong URL to a correct URL
82
- * keep track of renamed slugs, redirecting from old to new slugs
83
- * translate categories and tags slugs.
1
  === Qtranslate Slug ===
2
  Contributors: Carlos Sanz García
3
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SYC46KSLRC4Q8
4
  Tags: qtranslate, slug, multilanguage
5
+ Requires at least: 3.3
6
+ Tested up to: 3.4
7
+ Version: 1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Adds support for permalink translations and fix some QTranslate deficiencies since wordpress 3.0
12
 
13
  == Description ==
14
 
15
+ [Qtranslate](http://wordpress.org/extend/plugins/qtranslate/) is a nice plugin but unfortunately today is **outdated**. **Qtranslate Slug** is an addon to QTranslate, which adds support for permalinks translations and fix some QTranslate deficiencies since wordpress 3.0.
 
16
 
17
+ **Version 1.0** has been written from scratch using OOP. The code has been structured better, the functions have been marked and commented and everything is better integrated with Wordpress API.
18
+
19
+ This plugin works with **Qtranslate** since **2.5.8**.
20
+
21
+ = What is new? =
22
+
23
+ * **works** with any permalink combination and qtranslate mode.
24
+ * new branch, the plugin has been rewritten: now the code is commented and wrapped inside a class, much code has change and the performance has been increased (use caches).
25
+ * data system changed, no ID for slug type, then it don't needs install `qtrasnlate_slug` table. That means slugs now are stored on meta tables and installation creates a termmeta table with some new *core functions* to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/). Upgrade process when the plugin updates from older versions.
26
+ * the plugin generates translated slug automatically from title in empty cases.
27
+ * the plugin checks if the slug already exists (per each language and `post_type`/`taxonomy`), and adds a progressive number in this case. Works on ajax requests for example when new taxonomies are created in edit post page.
28
+ * possibility to translate the base of permastructs for *post_types* and *taxonomies*, uses [$wp_rewrite](http://codex.wordpress.org/Class_Reference/WP_Rewrite). New admin options page for save the base permastructs.
29
+ * added some filters, see in [other notes](http://wordpress.org/extend/plugins/qtranslate-slug/other_notes/).
30
+ * added plugin language textdomain (.pot file).
31
+ * updated **Language selector Widget**, and some new conventions like accessible functions for templating.
32
+ * some bug fixes.
33
+ * some Qtranslate patches.
34
+
35
+
36
+ You can also check the [project website](http://not-only-code.github.com/qtranslate-slug/) hosted on [GitHub](http://not-only-code.github.com).
37
+ Thanks for use this plugin!
38
 
39
  == Installation ==
40
 
41
+ **This plugins requires [Qtranslate](http://wordpress.org/extend/plugins/qtranslate/) installed previously, if not, it will not activate.**
42
 
43
+ 1. Upload `qtranslate-slug` to the `/wp-content/plugins/` directory.
44
+ 1. Activate the plugin through the 'Plugins' menu in WordPress.
45
  1. That's all!
46
 
47
+ = Changing base permastructs =
48
+
49
+ 1. In admin: navigate to *Settings/Slug options*.
50
+ 1. Set the base permastructs for **post types** and **taxonomies** (If you setup a base permastruct for *categories* or *tags* in *Settings/Permalinks*, these will be overwritten by the translated ones).
51
+ 1. Save settings and that's all!
52
+
53
  == Frequently Asked Questions ==
54
 
55
+ = It works with posts and pages, but with other content type? =
56
 
57
  This plugin allows to translate slugs of: posts, pages, custom post types, categories, tags and custom taxonomies.
58
 
59
+ = Do I have to configure anything? =
60
+
61
+ If you want to translate also the base permastructs (ex. *category*, *tag*, etc). Visit the plugin settings page in the admin *Settings/Slug options*
62
+
63
+ = How can i insert a language selector in my theme ? =
64
+
65
+ You can choose to:
66
+ * use **Qtranslate Slug Widget** in your sidebar.
67
+ * place in your template `<?php if (function_exists('qts_language_menu') ) qts_language_menu('text'); ?>`. Options are: `dropdown`, `text`, `image`, and `both`.
68
+
69
+ = Appears an error 404, what can i do? =
70
+
71
+ In the admin go to *Settings/Permalinks* or *Settings/Slug options* and save.
72
+
73
+ = I can't manage translations in Nav Menus. =
74
 
75
+ That's because language selector metabox is hidden, if you are in admin *nav menus* screen, press the button **Screen options** (on top and right) and after, check the option *Languages*. It will appear a **Language** meta box on top of the left sidebar.
76
 
77
  == Screenshots ==
78
 
79
+ 1. Edit page for: post / page / post_type, you can see the meta box for translated slugs on top and right.
80
+ 2. Add new taxonomy page
81
+ 3. Edit taxonomy page
82
+ 4. Qtranslate Slug options page for translate base permastructs of post_types and taxonomies.
83
 
84
  == Changelog ==
85
 
86
+ = 1.0 =
87
+ * **works** with any permalink combination and qtranslate mode.
88
+ * new branch, the plugin has been rewritten: now the code is commented and wrapped inside a class, much code has change and the performance has been increased (use caches).
89
+ * data system changed, no ID for slug type, then it don't needs install `qtrasnlate_slug` table. That means slugs now are stored on meta tables and installation creates a termmeta table with some new *core functions* to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/). Upgrade process when the plugin updates from older versions.
90
+ * the plugin generates translated slug automatically from title in empty cases.
91
+ * the plugin checks if the slug already exists (per each language and `post_type`/`taxonomy`), and adds a progressive number in this case. Works on ajax requests for example when new taxonomies are created in edit post page.
92
+ * possibility to translate the base of permastructs for *post_types* and *taxonomies*, uses [$wp_rewrite](http://codex.wordpress.org/Class_Reference/WP_Rewrite). New admin options page for save the base permastructs.
93
+ * added some filters, see in [other notes](http://wordpress.org/extend/plugins/qtranslate-slug/other_notes/).
94
+ * added plugin language textdomain (.pot file).
95
+ * updated **Language selector Widget**, and some new conventions like accessible functions for templating.
96
+ * some bug fixes.
97
+ * some Qtranslate patches.
98
+
99
  = 0.9 =
100
  * some wordpress qTranslate bug fixes
101
  * adds a javascript solution for qTranslate Nav Menus
106
  * added support por Taxonomies
107
  * added support por Custom Post Types
108
 
109
+ = 0.7 = [Zapo](http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499)
110
  * added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit
111
 
112
  = 0.5 and 0.6 enhanched by Marco Del Percio =
113
 
114
  == Upgrade Notice ==
115
 
116
+ = 1.0 =
117
+ Major version, the plugin has been rewritten. Better performance, and some enhancements.
118
+
119
  = 0.9 =
120
  This version fix some bugs and allow multilanguage in nav-menus.
121
 
126
  This version allows TLD domain option for a different Qtranslate fork maded by Zappo
127
 
128
 
129
+ == Other notes ==
130
+
131
+ Plugin filters reference:
132
+
133
+ = qts_validate_post_slug =
134
+
135
+ filter to process the post slug before is saved on the database.
136
+ `args: $post (object), $slug (string), $lang (string)`
137
+
138
+ = qts_validate_term_slug =
139
+
140
+ filter to process the term slug before is saved on the database.
141
+ `args: $term (object), $slug (string), $lang (string)`
142
+
143
+ = qts_url_args =
144
+
145
+ filter to process the entire url after it has been generated.
146
+ `args: $url (string), $lang (string)`
147
+
148
+ = qts_permastruct =
149
+
150
+ filter to process the permastruct, used for change the base.
151
+ `args: $permastruct (string), $name (string)`
152
+
153
+
154
+ = Todo =
155
 
156
+ * detect Slug for each language and redirect accordingly in parse_query.
157
+ * expand qtranslate for translate attachment names and descriptions ( useful for galleries )
158
+ * translate other slugs like attachments.
159
+ * multisite: add suport as network plugin enhancing the request, some qtranslate patches.
160
+ * qtranslate integration with other plugins like Jigoshop, e-commerce, etc. Addapt **$wp_rewrite**.
 
 
 
 
assets/css/qts-settings.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*messages*/
2
+ .error {color:#cc0000;}
3
+
4
+ .form-table th {
5
+ width: 15%;
6
+ min-width: 15% !important;
7
+ }
8
+
9
+ .form-table td > span {
10
+ display: inline-block;
11
+ min-width: 100px;
12
+ }
13
+ .qts-slug {
14
+ width: 35%;
15
+ }
16
+
17
+ #qts-loading {
18
+ display: none;
19
+ position: relative;
20
+ margin-left: 5px;
21
+ vertical-align: middle;
22
+ }
23
+
24
+ div.updated.success{
25
+ border-color: #298e00;
26
+ background-color: #D4EDC9;
27
+ }
28
+
29
+ .error a.button-primary {
30
+ color: white !important;
31
+ text-decoration: none !important;
32
+ }
33
+
34
+ .ko {
35
+ color: #c00;
36
+ }
js/qt-nav-menu-min.js → assets/js/qts-nav-menu-min.js RENAMED
File without changes
js/qt-nav-menu.js → assets/js/qts-nav-menu.js RENAMED
File without changes
assets/js/qts-settings-upgrade.js ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($) {
2
+
3
+ function _debug(msg) {
4
+ if(window.console) {
5
+ console.debug(msg);
6
+ }
7
+ }
8
+ var upgrade_box = $('#qts-upgrade-box'),
9
+ upgrade_form = $('#qts-upgrade-form'),
10
+ upgrade_button = $('#qts-upgrade-button'),
11
+ notice_status = function(_status) {
12
+ upgrade_box.removeClass().addClass(_status);
13
+ },
14
+ block_form = function(_block) {
15
+ if (_block) {
16
+ $('#qts-loading').show();
17
+ upgrade_button.attr('disabled', true);
18
+ } else {
19
+ $('#qts-loading').hide();
20
+ upgrade_button.attr('disabled', false);
21
+ }
22
+
23
+ },
24
+ check_types = function(_response) {
25
+
26
+ block_form(false);
27
+ upgrade_form.find('.message').remove();
28
+
29
+ switch (_response.status) {
30
+ default:
31
+ case 0:
32
+ upgrade_form.prepend('<p class=\'message ko\'>'+_response.message+'</p>');
33
+ break;
34
+ case 1:
35
+ notice_status('updated success');
36
+ upgrade_form.remove();
37
+ upgrade_box.append('<p><strong>'+_response.message+'</strong></p>');
38
+ upgrade_box.delay(2500).fadeTo(1300, 0, function(){ upgrade_box.remove(); });
39
+ break;
40
+ case 2:
41
+ var data_ = '<p class=\'message\'>'+_response.message+'</p>';
42
+ data_ += '<select id=\'qts-slug-type\' class=\'message\'>';
43
+
44
+ for (opt in _response.options)
45
+ data_ += '<option value=\''+opt+'\'>'+_response.options[opt]+'</option>';
46
+ data_ += '</select>';
47
+
48
+ upgrade_form.prepend(data_);
49
+
50
+ break;
51
+ }
52
+ },
53
+ start_upgrade = function(_event) {
54
+ _event.preventDefault();
55
+
56
+ notice_status('updated');
57
+ block_form(true);
58
+
59
+ var package_ = {};
60
+ package_.action = $('#qts-upgrade-action').val();
61
+ package_.nonce = $('#qts-upgrade-nonce').val();
62
+ if ( $('#qts-slug-type').length )
63
+ package_.type = $('#qts-slug-type').val();
64
+
65
+ $.post(ajaxurl, package_, check_types);
66
+ }
67
+
68
+ upgrade_button.bind('click', start_upgrade);
69
+ });
assets/js/qts-settings.js ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*############### Error messages ######################*/
2
+ jQuery(function(){
3
+
4
+ var error_msg = jQuery("#message p[class='setting-error-message']");
5
+ // look for admin messages with the "setting-error-message" error class
6
+ if (error_msg.length != 0) {
7
+ // get the title
8
+ var error_setting = error_msg.attr('title');
9
+
10
+ // look for the label with the "for" attribute=setting title and give it an "error" class (style this in the css file!)
11
+ jQuery("label[for='" + error_setting + "']").addClass('error');
12
+
13
+ // look for the input with id=setting title and add a red border to it.
14
+ jQuery("input[id='" + error_setting + "']").attr('style', 'border-color: red');
15
+ }
16
+
17
+
18
+
19
+ });
languages/qts-es_ES.mo ADDED
Binary file
languages/qts-es_ES.po ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2012 qTranslate slug
2
+ # This file is distributed under the same license as the qTranslate slug package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: qTranslate slug 1.0\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/qtranslate-slug\n"
7
+ "POT-Creation-Date: 2012-05-27 20:27:55+00:00\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2012-06-17 03:37+0100\n"
12
+ "Last-Translator: Carlos Sanz <carlos.sanz@gmail.com>\n"
13
+ "Language-Team: Carlos Sanz Garcia <carlos.sanz@gmail.com>\n"
14
+
15
+ # qtranslate-slug.php
16
+ msgid "Language selector"
17
+ msgstr "Selector de idioma"
18
+
19
+ # qtranslate-slug.php
20
+ msgid "Title:"
21
+ msgstr "Título:"
22
+
23
+ # qtranslate-slug.php
24
+ msgid "<p style=\"color:red\">This plugin requires qTranslate to be installed and activated.</p>"
25
+ msgstr "<p style=\"color:red\">Este plugin necesita qTranslate instalado y activado previamente.</p>"
26
+
27
+ # qtranslate-slug.php
28
+ msgid "Slug"
29
+ msgstr "Enlace permanente"
30
+
31
+ # qtranslate-slug.php
32
+ msgid "Show short name (en):"
33
+ msgstr "Mostrar nombre corto (en):"
34
+
35
+ # qtranslate-slug-settings-options.php
36
+ msgid "Post types"
37
+ msgstr "Post types"
38
+
39
+ # qtranslate-slug-settings-options.php
40
+ msgid "Taxonomies"
41
+ msgstr "Taxonomias"
42
+
43
+ # qtranslate-slug-settings-options.php
44
+ msgid "Slug (%s)"
45
+ msgstr "URL (%s)"
46
+
47
+ # qtranslate-slug-settings-options.php
48
+ msgid "<code>http://example.org/<u>%s</u>/some-%s/</code>"
49
+ msgstr "<code>http://ejemplo.org/<u>%s</u>/algun-%s/</code>"
50
+
51
+ # qtranslate-slug-settings-options.php
52
+ msgid "<code>http://example.org/<u>category</u>/some-category/</code>"
53
+ msgstr "<code>http://ejemplo.org/<u>categoria</u>/alguna-categoria/</code>"
54
+
55
+ # qtranslate-slug-settings-options.php
56
+ msgid "<code>http://example.org/<u>tag</u>/some-tag/</code>"
57
+ msgstr "<code>http://ejemplo.org/<u>etiqueta</u>/alguna-etiqueta/</code>"
58
+
59
+ # qtranslate-slug-settings.php
60
+ msgid "Qtranslate Slug options"
61
+ msgstr "Opciones de Qtranslate Slug"
62
+
63
+ # qtranslate-slug-settings.php
64
+ msgid "Slug options"
65
+ msgstr "Opciones de URL"
66
+
67
+ # qtranslate-slug-settings.php
68
+ msgid "Save Changes"
69
+ msgstr "Guardar cambios"
70
+
71
+ # qtranslate-slug-settings.php
72
+ msgid "Expecting a Numeric value! Please fix."
73
+ msgstr "Se espera un valor numérico! Por favor, corrígelo."
74
+
75
+ # qtranslate-slug-settings.php
76
+ msgid "Expecting comma separated numeric values! Please fix."
77
+ msgstr "Se esperan valores numéricos separados por coma! Por favor, corrígelo."
78
+
79
+ # qtranslate-slug-settings.php
80
+ msgid "Invalid email"
81
+ msgstr "E-mail incorrecto"
82
+
83
+ # qtranslate-slug-settings.php
84
+ msgid "This setting field cannot be empty! Please enter a valid email address."
85
+ msgstr "Este campo no puede estar vacío! Por favor introduce una dirección de e-mail válida."
86
+
87
+ # qtranslate-slug-settings.php
88
+ msgid "Please enter a valid email address."
89
+ msgstr "Por favor introduce una dirección de e-mail válida."
90
+
91
+ # qtranslate-slug-settings.php
92
+ msgid "upgrade now"
93
+ msgstr "actualizar ahora"
94
+
95
+ # qtranslate-slug.php
96
+ msgid "Please update your old data to the new system."
97
+ msgstr "Por favor actualiza tu antiguo sistema de datos al nuevo."
98
+
99
+ # qtranslate-slug-settings.php
100
+ msgid "Upgrade your data"
101
+ msgstr "Actualiza tus datos"
102
+
103
+ # qtranslate-slug-settings.php
104
+ msgid "There are slugs stored with old data system. Please upgrade your data pressing upgrade button:"
105
+ msgstr "Hay slugs almacenados en el antiguo sistema. Por favor actualiza tus datos aprentando el botón actualizar:"
106
+
107
+ # qtranslate-slug-settings.php
108
+ msgid "Sorry, some error happened. Refresh this page and try again please."
109
+ msgstr "Lo sentimos, algún tipo de error ha ocurrido. Por favor recarga esta página y prueba otra vez."
110
+
111
+ # qtranslate-slug-settings.php
112
+ msgid "Congratulations, your data has been upgraded, you are up to date."
113
+ msgstr "Felicidades, tus datos se han actualizado, ahora estás al día."
114
+
115
+ # qtranslate-slug-settings.php
116
+ msgid "One step more, select what type of slug is this: <strong>%s</strong>"
117
+ msgstr "Un paso más, selecction qué tipo de slug es este: <strong>%s</strong>"
118
+
119
+ # qtranslate-slug-settings.php
120
+ msgid "Post, Page or Custom post type"
121
+ msgstr "Entrada, Página o Custom post type"
122
+
123
+ # qtranslate-slug-settings.php
124
+ msgid "Category, tag or custom taxonomy"
125
+ msgstr "Categoria, tag o taxonomía"
126
+
127
+ # qtranslate-slug.php
128
+ msgid "This plugin requires at least <strong>Wordpress 3.3</strong> and <strong>Qtranslate(2.5.8 or newer)</strong>"
129
+ msgstr "Este plugin requiere al menos <strong>Wordpress 3.3</strong> y <strong>Qtranslate(2.5.8 o mayor)</strong>"
130
+
131
+ # qtranslate-slug-settings.php
132
+ msgid "If you activated previously the <a href=\"options-permalink.php\">pretty permalinks</a>, in this section you can translate the <abbr title=\"en inglés, Universal Resource Locator\">URLs</abbr> <strong>bases</strong> for <a href=\"http://codex.wordpress.org/Function_Reference/register_post_type#Arguments\">public</a> post_types, categories, tags and taxonomies."
133
+ msgstr "Si has activado previamente los <a href=\"options-permalink.php\">enlaces permanentes</a>, en esta sección podrás traducir las <strong>bases</strong> de las <abbr title=\"en inglés, Universal Resource Locator\">URLs</abbr> para post_types, categorías, etiquetas y taxonomias <a href=\"http://codex.wordpress.org/Function_Reference/register_post_type#Arguments\">públicas</a>."
134
+
135
+ # qtranslate-slug-settings.php
136
+ msgid "For example, the post_type <kbd>books</kbd>, in Spanish would be displayed as <code>http://example.org/es/libros/post-type-name/</code>. If you leave this blank will use the default option when you <a href=\"http://codex.wordpress.org/Function_Reference/register_post_type\">registered</a> the post_type."
137
+ msgstr "Por ejemplo, para el post_type <kbd>books</kbd> en Español se mostraría como <code>http://example.org/es/libros/post-type-name/</code>. Si dejas esto en blanco se usará la opción predeterminada cuando <a href=\"http://codex.wordpress.org/Function_Reference/register_post_type\">registraste</a> el post_type."
138
+
139
+ # qtranslate-slug-settings.php
140
+ msgid "For example, the taxonomy <kbd>category</kbd>, in Spanish would be displayed as <code>http://example.org/es/categoria/taxonomy-name/</code>. If you leave this blank will use the default option when you <a href=\"http://codex.wordpress.org/Function_Reference/register_taxonomy\">registered</a> the taxonomy (if you previously setup a base permastruct for <u>categories</u> or <u>tags</u> in <a href=\"options-permalink.php\">permalinks</a> page, these bases will be overwritten by the translated ones)."
141
+ msgstr "Por ejemplo, la taxonomia <kbd>category</kbd>, en Español se mostraría como <code>http://example.org/es/categoria/taxonomy-name/</code>. Si dejas esto en blanco se usará la opción predeterminada cuando <a href=\"http://codex.wordpress.org/Function_Reference/register_taxonomy\">registraste</a> la texonomia (si previamente configuraste la base de las estructuraas de <u>categorías</u> o <u>tags</u> en la página <a href=\"options-permalink.php\">enlaces permanentes</a>, estas bases serán reemplazadas por las traducidas)."
142
+
languages/qts.pot ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2012 qTranslate slug
2
+ # This file is distributed under the same license as the qTranslate slug package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: qTranslate slug 1.0\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/qtranslate-slug\n"
7
+ "POT-Creation-Date: 2012-05-27 20:27:55+00:00\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2012-MO-DA HO:MI+ZONE\n"
12
+ "Last-Translator: Carlos Sanz Garcia <carlos.sanz@gmail.com>\n"
13
+ "Language-Team: Carlos Sanz Garcia <carlos.sanz@gmail.com>\n"
14
+
15
+ #: qtranslate-slug.php
16
+ msgid "Language selector"
17
+ msgstr ""
18
+
19
+ #: qtranslate-slug.php
20
+ msgid "Title:"
21
+ msgstr ""
22
+
23
+ #: qtranslate-slug.php
24
+ msgid "<p style="color:red">This plugin requires qTranslate to be installed and activated.</p>"
25
+ msgstr ""
26
+
27
+ #: qtranslate-slug.php
28
+ #: qtranslate-slug.php
29
+ #: qtranslate-slug.php
30
+ msgid "Slug"
31
+ msgstr ""
32
+
33
+ #: qtranslate-slug.php
34
+ msgid "Show short name (en):"
35
+ msgstr ""
36
+
37
+ #: qtranslate-slug-settings-options.php
38
+ msgid "Post types"
39
+ msgstr ""
40
+
41
+ #: qtranslate-slug-settings-options.php
42
+ msgid "Taxonomies"
43
+ msgstr ""
44
+
45
+ #: qtranslate-slug-settings-options.php
46
+ msgid "Slug (%s)"
47
+ msgstr ""
48
+
49
+ #: qtranslate-slug-settings-options.php
50
+ msgid "<code>http://example.org/<u>%s</u>/some-%s/</code>"
51
+ msgstr ""
52
+
53
+ #: qtranslate-slug-settings-options.php
54
+ msgid "<code>http://example.org/<u>category</u>/some-category/</code>"
55
+ msgstr ""
56
+
57
+ #: qtranslate-slug-settings-options.php
58
+ msgid "<code>http://example.org/<u>tag</u>/some-tag/</code>"
59
+ msgstr ""
60
+
61
+ #: qtranslate-slug-settings-options.php
62
+ msgid "<code>http://example.org/<u>%s</u>/some-%s/</code>"
63
+ msgstr ""
64
+
65
+ #: qtranslate-slug-settings.php
66
+ msgid "Qtranslate Slug options"
67
+ msgstr ""
68
+
69
+ #: qtranslate-slug-settings.php
70
+ msgid "Slug options"
71
+ msgstr ""
72
+
73
+ #: qtranslate-slug-settings.php
74
+ msgid "Save Changes"
75
+ msgstr ""
76
+
77
+ #: qtranslate-slug-settings.php
78
+ msgid "Expecting a Numeric value! Please fix."
79
+ msgstr ""
80
+
81
+ #: qtranslate-slug-settings.php
82
+ msgid "Expecting comma separated numeric values! Please fix."
83
+ msgstr ""
84
+
85
+ #: qtranslate-slug-settings.php
86
+ msgid "Invalid email"
87
+ msgstr ""
88
+
89
+ #: qtranslate-slug-settings.php
90
+ msgid "This setting field cannot be empty! Please enter a valid email address."
91
+ msgstr ""
92
+
93
+ #: qtranslate-slug-settings.php
94
+ msgid "Please enter a valid email address."
95
+ msgstr ""
96
+
97
+ #: qtranslate-slug-settings.php
98
+ #: qtranslate-slug-settings.php
99
+ msgid "upgrade now"
100
+ msgstr ""
101
+
102
+ #: qtranslate-slug.php
103
+ msgid "Please update your old data to the new system."
104
+ msgstr ""
105
+
106
+ #: qtranslate-slug-settings.php
107
+ msgid "Upgrade your data"
108
+ msgstr ""
109
+
110
+ #: qtranslate-slug-settings.php
111
+ msgid "There are slugs stored with old data system. Please upgrade your data pressing upgrade button:"
112
+ msgstr ""
113
+
114
+ #: qtranslate-slug-settings.php
115
+ msgid "Sorry, some error happened. Refresh this page and try again please."
116
+ msgstr ""
117
+
118
+ #: qtranslate-slug-settings.php
119
+ msgid "Congratulations, your data has been upgraded, you are up to date."
120
+ msgstr ""
121
+
122
+ #: qtranslate-slug-settings.php
123
+ msgid "One step more, select what type of slug is this: <strong>%s</strong>"
124
+ msgstr ""
125
+
126
+ #: qtranslate-slug-settings.php
127
+ msgid "Post, Page or Custom post type"
128
+ msgstr ""
129
+
130
+ #: qtranslate-slug-settings.php
131
+ msgid "Category, tag or custom taxonomy"
132
+ msgstr ""
133
+
134
+ #: qtranslate-slug.php
135
+ msgid "This plugin requires at least <strong>Wordpress 3.3</strong> and <strong>Qtranslate(2.5.8 or newer)</strong>"
136
+ msgstr ""
137
+
138
+ #: qtranslate-slug-settings.php
139
+ msgid "If you activated previously the <a href=\"/options-permalink.php\">pretty permalinks</a>, in this section you can translate the <abbr title=\"en inglés, Universal Resource Locator\">URLs</abbr> <strong>bases</strong> for <a href=\"http://codex.wordpress.org/Function_Reference/register_post_type#Arguments\">public</a> post_types, categories, tags and taxonomies."
140
+ msgstr ""
141
+
142
+ #: qtranslate-slug-settings.php
143
+ msgid "For example, the post_type <kbd>books</kbd>, in Spanish would be displayed as <code>http://example.org/es/libros/post-type-name/</code>. If you leave this blank will use the default option when you <a href=\"http://codex.wordpress.org/Function_Reference/register_post_type\">registered</a> the post_type."
144
+ msgstr ""
145
+
146
+ #: qtranslate-slug-settings.php
147
+ msgid "For example, the taxonomy <kbd>category</kbd>, in Spanish would be displayed as <code>http://example.org/es/categoria/taxonomy-name/</code>. If you leave this blank will use the default option when you <a href=\"http://codex.wordpress.org/Function_Reference/register_taxonomy\">registered</a> the taxonomy (if you previously setup a base permastruct for <u>categories</u> or <u>tags</u> in <a href="options-permalink.php">permalinks</a> page, these bases will be overwritten by the translated ones)."
148
+ msgstr ""
qtranslate-slug-settings-options.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Define our settings sections
4
+ *
5
+ * @package Qtranslate Slug
6
+ * @subpackage Settings
7
+ * @version 1.0
8
+ *
9
+ * @return array key=$id, array value=$title in: add_settings_section( $id, $title, $callback, $page );
10
+ */
11
+ function qts_options_page_sections() {
12
+
13
+ $sections = array();
14
+ $sections['post_types'] = __('Post types', 'qts');
15
+ $sections['taxonomies'] = __('Taxonomies', 'qts');
16
+
17
+ return $sections;
18
+ }
19
+
20
+
21
+
22
+ /**
23
+ * Helper for create arrays of choices
24
+ *
25
+ * @package Qtranslate Slug
26
+ * @subpackage Settings
27
+ * @version 1.0
28
+ *
29
+ * @return array
30
+ */
31
+ function get_multi_txt_choices($name = false) {
32
+ global $q_config;
33
+
34
+ if (!$name) return array();
35
+
36
+ $choices = array();
37
+ foreach( $q_config['enabled_languages'] as $key => $lang) {
38
+ $label = sprintf( __('Slug (%s)', 'qts'), $q_config['language_name'][$lang] );
39
+ $choices[] = "$label|$lang"; // prints: 'Slug (English)|en' ( $name = books )
40
+ }
41
+
42
+ return $choices;
43
+ }
44
+
45
+
46
+ /**
47
+ * Define our form fields (settings)
48
+ *
49
+ * @package Qtranslate Slug
50
+ * @subpackage Settings
51
+ * @version 1.0
52
+ *
53
+ * @return array
54
+ */
55
+ function qts_options_page_fields() {
56
+ global $q_config;
57
+
58
+ $post_types = get_post_types( array('_builtin' => false, 'public' => true ), 'objects');
59
+
60
+ // each post type
61
+ foreach ($post_types as $post_type):
62
+
63
+ $options[] = array(
64
+ "section" => "post_types",
65
+ "id" => QTS_PREFIX . "post_type_" . $post_type->name,
66
+ "title" => $post_type->labels->singular_name,
67
+ "desc" => sprintf( __( '<code>http://example.org/<u>%s</u>/some-%s/</code>', 'qts' ), $post_type->name, $post_type->name),
68
+ 'class' => 'qts-slug',
69
+ "type" => "multi-text",
70
+ "choices" => get_multi_txt_choices( $post_type->name),
71
+ "std" => ""
72
+ );
73
+
74
+ endforeach;
75
+ // end each post type
76
+
77
+ $options[] = array(
78
+ "section" => "taxonomies",
79
+ "id" => QTS_PREFIX . "taxonomy_category",
80
+ "title" => __('Categories'),
81
+ "desc" => __( '<code>http://example.org/<u>category</u>/some-category/</code>', 'qts' ),
82
+ "type" => "multi-text",
83
+ 'class' => 'qts-slug',
84
+ "choices" => get_multi_txt_choices('category'),
85
+ "std" => ""
86
+ );
87
+
88
+ $options[] = array(
89
+ "section" => "taxonomies",
90
+ "id" => QTS_PREFIX . "taxonomy_post_tag",
91
+ "title" => __('Tags'),
92
+ "desc" => __( '<code>http://example.org/<u>tag</u>/some-tag/</code>', 'qts' ),
93
+ "type" => "multi-text",
94
+ 'class' => 'qts-slug',
95
+ "choices" => get_multi_txt_choices('post_tag'),
96
+ "std" => ""
97
+ );
98
+
99
+
100
+ $taxonomies = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => false ), 'object' );
101
+
102
+ // each extra taxonomy
103
+ foreach ($taxonomies as $taxonomy):
104
+
105
+ $options[] = array(
106
+ "section" => "taxonomies",
107
+ "id" => QTS_PREFIX . "taxonomy_" . $taxonomy->name,
108
+ "title" => $taxonomy->labels->singular_name,
109
+ "desc" => sprintf( __( '<code>http://example.org/<u>%s</u>/some-%s/</code>', 'qts' ), $taxonomy->name, $taxonomy->name ),
110
+ "type" => "multi-text",
111
+ 'class' => 'qts-slug',
112
+ "choices" => get_multi_txt_choices( $taxonomy->name),
113
+ "std" => ""
114
+ );
115
+
116
+ endforeach;
117
+ // end each extra taxonomy
118
+
119
+ return $options;
120
+ }
121
+
122
+
123
+
124
+ /**
125
+ * Contextual Help
126
+ *
127
+ * @package Qtranslate Slug
128
+ * @subpackage Settings
129
+ * @version 1.0
130
+ *
131
+ */
132
+ function qts_options_page_contextual_help() {
133
+
134
+
135
+ $text = "<h3>" . __('Qtranslate Settings - Contextual Help','qts') . "</h3>";
136
+ $text .= "<p>" . __('Contextual help goes here. You may want to use different html elements to format your text as you want.','qts') . "</p>";
137
+
138
+ return $text;
139
+ }
qtranslate-slug-settings.php ADDED
@@ -0,0 +1,959 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // page settings sections & fields as well as the contextual help text.
4
+ include_once('qtranslate-slug-settings-options.php');
5
+
6
+
7
+ /**
8
+ * Prints upgrade form in Qtranslate Slug admin page
9
+ *
10
+ * @package Qtranslate Slug
11
+ * @subpackage Settings
12
+ * @version 1.0
13
+ *
14
+ * @return array
15
+ */
16
+ function qts_upgrade() {
17
+ global $qtranslate_slug;
18
+
19
+ if ( !$qtranslate_slug->check_old_data() ) return;
20
+
21
+ echo "<div id=\"qts-upgrade-box\" class=\"updated\" style=\"margin: 15px 0; margin-bottom:25px; padding: 10px\">" . PHP_EOL;
22
+
23
+ echo "<h3>" . __('Upgrade your data', 'qts') . "</h3>" . PHP_EOL;
24
+ echo "<p>" . __('There are slugs stored with old data system. Please upgrade your data pressing upgrade button:', 'qts') . "</p>" . PHP_EOL;
25
+
26
+ echo "<div id=\"qts-upgrade-form\">" . PHP_EOL;
27
+ echo "<input type=\"hidden\" id=\"qts-upgrade-action\" name=\"qts-upgrade-action\" value=\"qts-upgrade-check\" />" .PHP_EOL;
28
+ echo "<input type=\"hidden\" id=\"qts-upgrade-nonce\" name=\"qts-upgrade-nonce\" value=\"". wp_create_nonce('qts-upgrade') . "\" />" .PHP_EOL;
29
+ echo "<p><a id=\"qts-upgrade-button\" href=\"#\" class=\"button-primary\">" . __('upgrade now', 'qts') . "</a><img src=\"".admin_url('images/wpspin_light.gif')."\" class=\"qts-loading\" id=\"qts-loading\" alt=\"\"></p>" . PHP_EOL;
30
+ echo "</div></div>" . PHP_EOL;
31
+ }
32
+
33
+
34
+ /**
35
+ * AJAX: upgrade old database to new system
36
+ *
37
+ * @package Qtranslate Slug
38
+ * @subpackage Settings
39
+ * @version 1.0
40
+ *
41
+ * @return boolean
42
+ */
43
+ function qts_process_old_data( $old_data = null, $type = 'post' ) {
44
+ global $wpdb, $qtranslate_slug;
45
+
46
+ if ( is_null($old_data) || empty($old_data) ) return 0;
47
+ foreach ($old_data as $row) {
48
+ switch ($row->qts_type) {
49
+ case 1:
50
+ case 2:
51
+ update_post_meta( $row->qts_id, $qtranslate_slug->get_meta_key($row->qts_lang), $row->qts_slug);
52
+ break;
53
+ case 3:
54
+ case 4:
55
+ update_term_meta( $row->qts_id, $qtranslate_slug->get_meta_key($row->qts_lang), $row->qts_slug);
56
+ break;
57
+ case 5:
58
+ if ($type == 'post')
59
+ update_post_meta( $row->qts_id, $qtranslate_slug->get_meta_key($row->qts_lang), $row->qts_slug);
60
+
61
+ if ($type == 'term')
62
+ update_term_meta( $row->qts_id, $qtranslate_slug->get_meta_key($row->qts_lang), $row->qts_slug);
63
+ break;
64
+ };
65
+ }
66
+ $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}qtranslate_slug");
67
+
68
+ return 1;
69
+ }
70
+
71
+ function qts_upgrade_response($type = 0, $slug = null) {
72
+ switch ( $type ) {
73
+ default:
74
+ case 0:
75
+ $response = array(
76
+ 'status' => 0,
77
+ 'message' => __('Sorry, some error happened. Refresh this page and try again please.', 'qts'),
78
+ );
79
+ break;
80
+
81
+ case 1:
82
+ $response = array(
83
+ 'status' => 1,
84
+ 'message' => __('Congratulations, your data has been upgraded, you are up to date.', 'qts'),
85
+ );
86
+ break;
87
+ case 2:
88
+ $response = array(
89
+ 'status' => 2,
90
+ 'message' => sprintf(__('One step more, select what type of slug is this: <strong>%s</strong>', 'qts'), $slug),
91
+ 'options' => array( 'post' => __('Post, Page or Custom post type', 'qts'), 'term' => __('Category, tag or custom taxonomy') )
92
+ );
93
+ break;
94
+ }
95
+
96
+ return $response;
97
+ }
98
+
99
+
100
+
101
+ /**
102
+ * AJAX: upgrade old database to new system
103
+ *
104
+ * @package Qtranslate Slug
105
+ * @subpackage Settings
106
+ * @version 1.0
107
+ *
108
+ * @return JSON object
109
+ */
110
+ function qts_upgrade_check() {
111
+ global $qtranslate_slug;
112
+
113
+ $old_data = $qtranslate_slug->check_old_data();
114
+
115
+ if ( wp_verify_nonce( $_POST['nonce'], 'qts-upgrade') ):
116
+
117
+ // if data process to save...
118
+ if ($old_data) {
119
+
120
+ // if defined data type 5, process to upgrade
121
+ if ( isset($_POST['type']) ):
122
+
123
+ $res = qts_process_old_data($old_data, $_POST['type']);
124
+
125
+ $response = qts_upgrade_response($res);
126
+
127
+ else :
128
+
129
+ // define wich type of data is 5
130
+ $array_of_5 = array();
131
+ foreach ( $old_data as $row )
132
+ if ( $row->qts_type == 5 ) $array_of_5[] = $row->qts_slug;
133
+
134
+ if (!empty($array_of_5)) $response = qts_upgrade_response(2, implode(', ', $array_of_5));
135
+
136
+ // if no data type 5, process to upgrade
137
+ if (!isset($response)) {
138
+ $res = qts_process_old_data($old_data);
139
+ $response = qts_upgrade_response($res);
140
+ }
141
+
142
+ endif;
143
+
144
+
145
+ // if not continue
146
+ } else {
147
+
148
+ $response = qts_upgrade_response();
149
+
150
+ }
151
+
152
+ else:
153
+
154
+ $response = qts_upgrade_response();
155
+
156
+ endif;
157
+
158
+ // response output
159
+ header( "Content-Type: application/json" );
160
+ echo json_encode($response);
161
+ exit;
162
+ }
163
+ add_action('wp_ajax_qts-upgrade-check', 'qts_upgrade_check');
164
+
165
+
166
+
167
+ /**
168
+ * Helper function for defining variables for the current page
169
+ *
170
+ * @package Qtranslate Slug
171
+ * @subpackage Settings
172
+ * @version 1.0
173
+ *
174
+ * @return array
175
+ */
176
+ function qts_get_settings() {
177
+
178
+ $output = array();
179
+
180
+ // put together the output array
181
+ $output['qts_option_name'] = QTS_OPTIONS_NAME; // the option name as used in the get_option() call.
182
+ $output['qts_page_title'] = __('Qtranslate Slug options', 'qts'); // the settings page title
183
+ $output['qts_page_sections'] = qts_options_page_sections(); // the setting section
184
+ $output['qts_page_fields'] = qts_options_page_fields(); // the setting fields
185
+ $output['qts_contextual_help'] = qts_options_page_contextual_help(); // the contextual help
186
+
187
+ return $output;
188
+ }
189
+
190
+
191
+
192
+ /**
193
+ * Helper function for registering our form field settings
194
+ *
195
+ * @package Qtranslate Slug
196
+ * @subpackage Settings
197
+ * @version 1.0
198
+ *
199
+ * src: http://alisothegeek.com/2011/01/wordpress-settings-api-tutorial-1/
200
+ * @param (array) $args The array of arguments to be used in creating the field
201
+ * @return function call
202
+ */
203
+ function qts_create_settings_field( $args = array() ) {
204
+ // default array to overwrite when calling the function
205
+ $defaults = array(
206
+ 'id' => 'default_field', // the ID of the setting in our options array, and the ID of the HTML form element
207
+ 'title' => 'Default Field', // the label for the HTML form element
208
+ 'desc' => 'This is a default description.', // the description displayed under the HTML form element
209
+ 'std' => '', // the default value for this setting
210
+ 'type' => 'text', // the HTML form element to use
211
+ 'section' => 'main_section', // the section this setting belongs to must match the array key of a section in qts_options_page_sections()
212
+ 'choices' => array(), // (optional): the values in radio buttons or a drop-down menu
213
+ 'class' => '' // the HTML form element class. Is used for validation purposes and may be also use for styling if needed.
214
+ );
215
+
216
+ // "extract" to be able to use the array keys as variables in our function output below
217
+ extract( wp_parse_args( $args, $defaults ) );
218
+
219
+ // additional arguments for use in form field output in the function qts_show_form_field!
220
+ $field_args = array(
221
+ 'type' => $type,
222
+ 'id' => $id,
223
+ 'desc' => $desc,
224
+ 'std' => $std,
225
+ 'choices' => $choices,
226
+ 'label_for' => $id,
227
+ 'class' => $class
228
+ );
229
+
230
+ add_settings_field( $id, $title, 'qts_show_form_field', __FILE__, $section, $field_args );
231
+
232
+ }
233
+
234
+
235
+
236
+ /**
237
+ * Register our setting, settings sections and settings fields
238
+ *
239
+ * @package Qtranslate Slug
240
+ * @subpackage Settings
241
+ * @version 1.0
242
+ *
243
+ */
244
+ function qts_register_settings(){
245
+
246
+ // get the settings sections array
247
+ $settings_output = qts_get_settings();
248
+ $qts_option_name = $settings_output['qts_option_name'];
249
+
250
+ //setting
251
+ register_setting($qts_option_name, $qts_option_name, 'qts_validate_options' );
252
+
253
+ //sections
254
+ if(!empty($settings_output['qts_page_sections'])){
255
+ // call the "add_settings_section" for each!
256
+ foreach ( $settings_output['qts_page_sections'] as $id => $title ) {
257
+ add_settings_section( $id, $title, 'qts_section_fn', __FILE__);
258
+ }
259
+ }
260
+
261
+ //fields
262
+ if(!empty($settings_output['qts_page_fields'])){
263
+ // call the "add_settings_field" for each!
264
+ foreach ($settings_output['qts_page_fields'] as $option) {
265
+ qts_create_settings_field($option);
266
+ }
267
+ }
268
+ }
269
+ add_action( 'admin_init', 'qts_register_settings' );
270
+
271
+
272
+
273
+ /**
274
+ * Group scripts (js & css)
275
+ *
276
+ * @package Qtranslate Slug
277
+ * @subpackage Settings
278
+ * @version 1.0
279
+ *
280
+ */
281
+ function qts_settings_scripts() {
282
+ global $qtranslate_slug;
283
+
284
+ wp_enqueue_style('qts_theme_settings_css', plugins_url( 'assets/css/qts-settings.css' , __FILE__ ) );
285
+ wp_enqueue_script( 'qts_theme_settings_js', plugins_url( 'assets/js/qts-settings.js' , __FILE__ ), array('jquery'));
286
+
287
+ if ($qtranslate_slug->check_old_data())
288
+ wp_enqueue_script('qts_theme_settings_upgrade_js', plugins_url( 'assets/js/qts-settings-upgrade.js' , __FILE__ ), array('jquery') );
289
+ }
290
+
291
+
292
+
293
+ /**
294
+ * The Admin menu page
295
+ *
296
+ * @package Qtranslate Slug
297
+ * @subpackage Settings
298
+ * @version 1.0
299
+ *
300
+ */
301
+ function qts_add_menu() {
302
+ global $current_screen;
303
+
304
+ $settings_output = qts_get_settings();
305
+ // collect our contextual help text
306
+ $qts_contextual_help = $settings_output['qts_contextual_help'];
307
+
308
+ // Display Settings Page link under the "Appearance" Admin Menu
309
+ $qts_settings_page = add_options_page(__('Qtranslate Slug options', 'qts'), __('Slug options', 'qts'), 'manage_options', QTS_PAGE_BASENAME, 'qts_show_settings_page');
310
+ // contextual help
311
+ /*
312
+ if ($qts_settings_page) {
313
+ $current_screen = get_current_screen();
314
+ //$current_screen->add_help_tab( array( $qts_settings_page, $qts_contextual_help ));
315
+ }
316
+ */
317
+ // css & js
318
+ add_action( 'load-'. $qts_settings_page, 'qts_settings_scripts' );
319
+ }
320
+ add_action( 'admin_menu', 'qts_add_menu' );
321
+
322
+
323
+
324
+ ////////////////////////////////////////////////////////////////////////////////////////
325
+
326
+ // Callback functions
327
+
328
+
329
+
330
+ /**
331
+ * Section HTML, displayed before the first option
332
+ *
333
+ * @package Qtranslate Slug
334
+ * @subpackage Settings
335
+ * @version 1.0
336
+ *
337
+ * @return echoes output
338
+ */
339
+ function qts_section_fn($page_section = false) {
340
+
341
+ if ( !$page_section || !isset($page_section['id']) ) return;
342
+
343
+ switch ($page_section['id']) {
344
+ case 'post_types':
345
+
346
+ echo "<p>" . __('For example, the post_type <kbd>books</kbd>, in Spanish would be displayed as <code>http://example.org/es/libros/post-type-name/</code>. If you leave this blank will use the default option when you <a href="http://codex.wordpress.org/Function_Reference/register_post_type">registered</a> the post_type.', 'qts') . "</p>";
347
+ break;
348
+
349
+ case 'taxonomies':
350
+
351
+ echo "<p>" . __('For example, the taxonomy <kbd>category</kbd>, in Spanish would be displayed as <code>http://example.org/es/categoria/taxonomy-name/</code>. If you leave this blank will use the default option when you <a href="http://codex.wordpress.org/Function_Reference/register_taxonomy">registered</a> the taxonomy (if you previously setup a base permastruct for <u>categories</u> or <u>tags</u> in <a href="options-permalink.php">permalinks</a> page, these bases will be overwritten by the translated ones).', 'qts') . "</p>";
352
+ break;
353
+ }
354
+ }
355
+
356
+
357
+
358
+ /**
359
+ * Form Fields HTML: all form field types share the same function
360
+ *
361
+ * @package Qtranslate Slug
362
+ * @subpackage Settings
363
+ * @version 1.0
364
+ *
365
+ * @return echoes output
366
+ */
367
+ function qts_show_form_field($args = array()) {
368
+ global $qtranslate_slug;
369
+
370
+ extract( $args );
371
+
372
+ // get the settings sections array
373
+ $settings_output = qts_get_settings();
374
+ $options = $qtranslate_slug->get_options();
375
+
376
+ // pass the standard value if the option is not yet set in the database
377
+ if ( !isset( $options[$id] ) && 'type' != 'checkbox' ) {
378
+ $options[$id] = $std;
379
+ }
380
+
381
+ // additional field class. output only if the class is defined in the create_setting arguments
382
+ $field_class = ($class != '') ? ' ' . $class : '';
383
+
384
+ // switch html display based on the setting type.
385
+ switch ( $type ) {
386
+ case 'text':
387
+ $options[$id] = stripslashes($options[$id]);
388
+ $options[$id] = esc_attr( $options[$id]);
389
+ echo "<input class='regular-text$field_class' type='text' id='$id' name='" . QTS_OPTIONS_NAME . "[$id]' value='$options[$id]' />";
390
+ echo ($desc != '') ? "<br /><span class='description'>$desc</span>" : "";
391
+ break;
392
+
393
+ case "multi-text":
394
+ foreach($choices as $item) {
395
+
396
+ $item = explode("|",$item); // cat_name|cat_slug
397
+ $item[0] = esc_html__($item[0], 'qts');
398
+
399
+ if (!empty($options[$id])) {
400
+ foreach ($options[$id] as $option_key => $option_val){
401
+ if ($item[1] == $option_key) {
402
+ $value = $option_val;
403
+ }
404
+ }
405
+ } else {
406
+ $value = '';
407
+ }
408
+
409
+ echo "<span>$item[0]:</span> <input class='$field_class' type='text' id='$id|$item[1]' name='" . QTS_OPTIONS_NAME . "[$id|$item[1]]' value='$value' /><br/>";
410
+ }
411
+ echo ($desc != '') ? "<span class='description'>$desc</span>" : "";
412
+ break;
413
+
414
+ case 'textarea':
415
+ $options[$id] = stripslashes($options[$id]);
416
+ $options[$id] = esc_html( $options[$id]);
417
+ echo "<textarea class='textarea$field_class' type='text' id='$id' name='" . QTS_OPTIONS_NAME . "[$id]' rows='5' cols='30'>$options[$id]</textarea>";
418
+ echo ($desc != '') ? "<br /><span class='description'>$desc</span>" : "";
419
+ break;
420
+
421
+ case 'select':
422
+ echo "<select id='$id' class='select$field_class' name='" . QTS_OPTIONS_NAME . "[$id]'>";
423
+ foreach($choices as $item) {
424
+ $value = esc_attr($item, 'qts');
425
+ $item = esc_html($item, 'qts');
426
+
427
+ $selected = ($options[$id]==$value) ? 'selected="selected"' : '';
428
+ echo "<option value='$value' $selected>$item</option>";
429
+ }
430
+ echo "</select>";
431
+ echo ($desc != '') ? "<br /><span class='description'>$desc</span>" : "";
432
+ break;
433
+
434
+ case 'select2':
435
+ echo "<select id='$id' class='select$field_class' name='" . QTS_OPTIONS_NAME . "[$id]'>";
436
+ foreach($choices as $item) {
437
+
438
+ $item = explode("|",$item);
439
+ $item[0] = esc_html($item[0], 'qts');
440
+
441
+ $selected = ($options[$id]==$item[1]) ? 'selected="selected"' : '';
442
+ echo "<option value='$item[1]' $selected>$item[0]</option>";
443
+ }
444
+ echo "</select>";
445
+ echo ($desc != '') ? "<br /><span class='description'>$desc</span>" : "";
446
+ break;
447
+
448
+ case 'checkbox':
449
+ echo "<input class='checkbox$field_class' type='checkbox' id='$id' name='" . QTS_OPTIONS_NAME . "[$id]' value='1' " . checked( $options[$id], 1, false ) . " />";
450
+ echo ($desc != '') ? "<br /><span class='description'>$desc</span>" : "";
451
+ break;
452
+
453
+ case "multi-checkbox":
454
+ foreach($choices as $item) {
455
+
456
+ $item = explode("|",$item);
457
+ $item[0] = esc_html($item[0], 'qts');
458
+
459
+ $checked = '';
460
+
461
+ if ( isset($options[$id][$item[1]]) ) {
462
+ if ( $options[$id][$item[1]] == 'true') {
463
+ $checked = 'checked="checked"';
464
+ }
465
+ }
466
+
467
+ echo "<input class='checkbox$field_class' type='checkbox' id='$id|$item[1]' name='" . QTS_OPTIONS_NAME . "[$id|$item[1]]' value='1' $checked /> $item[0] <br/>";
468
+ }
469
+ echo ($desc != '') ? "<br /><span class='description'>$desc</span>" : "";
470
+ break;
471
+ }
472
+ }
473
+
474
+
475
+
476
+ /**
477
+ * Validates base slugs per 'type' (post_type | taxonomy) and 'language'
478
+ *
479
+ * @package Qtranslate Slug
480
+ * @subpackage Settings
481
+ * @version 1.0
482
+ *
483
+ */
484
+ function qts_sanitize_bases($base_slugs = false) {
485
+
486
+ if ( !$base_slugs || empty($base_slugs) ) return;
487
+
488
+ $base_slugs_processed = array();
489
+ $post_types = array();
490
+ $taxonomies = array();
491
+
492
+ // changing array structure
493
+ foreach ($base_slugs as $type => $value) {
494
+
495
+ // matching post types..
496
+ preg_match('/(\b_qts_post_type_)\w+\b/', $type, $matches);
497
+
498
+ if (!empty($matches))
499
+ foreach ($value as $lang => $base) $post_types[$lang][$type] = $base;
500
+
501
+ // matching taxonomies..
502
+ preg_match('/(\b_qts_taxonomy_)\w+\b/', $type, $matches);
503
+
504
+ if (!empty($matches))
505
+ foreach ($value as $lang => $base) $taxonomies[$lang][$type] = $base;
506
+ }
507
+
508
+ // processing post_types
509
+ if ( count($post_types) > 1 )
510
+ $post_types = qts_prevent_duplicates($post_types);
511
+
512
+ // processing taxonomies
513
+ if ( count($taxonomies) > 1 )
514
+ $taxonomies = qts_prevent_duplicates($taxonomies);
515
+
516
+ foreach ($post_types as $lang => $array_)
517
+ foreach ($array_ as $key => $value) $base_slugs_processed[$key][$lang] = $value;
518
+
519
+ foreach ($taxonomies as $lang => $array_)
520
+ foreach ($array_ as $key => $value) $base_slugs_processed[$key][$lang] = $value;
521
+
522
+ return $base_slugs_processed;
523
+ }
524
+
525
+
526
+
527
+ /**
528
+ * Helper that prevents duplicates items on an array
529
+ *
530
+ * @package Qtranslate Slug
531
+ * @subpackage Settings
532
+ * @version 1.0
533
+ *
534
+ * @return array processed
535
+ */
536
+
537
+ function qts_prevent_duplicates($array) {
538
+
539
+ foreach ($array as $lang_ => $lang):
540
+
541
+ $values = array();
542
+ $processed = array_unique($lang);
543
+
544
+ while ( count($processed) != count($lang) ) {
545
+ $diff = count($lang) - count($processed);
546
+ foreach ($lang as $key => $value) {
547
+ if (!in_array($value, $values)) {
548
+ $values[] = $value;
549
+ } else {
550
+ $lang[$key] = "$value-$diff";
551
+ }
552
+ }
553
+ $processed = array_unique($lang);
554
+ }
555
+ $array[$lang_] = $lang;
556
+
557
+ endforeach;
558
+
559
+ return $array;
560
+ }
561
+
562
+
563
+
564
+ /**
565
+ * Admin Settings Page HTML
566
+ *
567
+ * @package Qtranslate Slug
568
+ * @subpackage Settings
569
+ * @version 1.0
570
+ *
571
+ * @return echoes output
572
+ */
573
+ function qts_show_settings_page() {
574
+ // get the settings sections array
575
+ $settings_output = qts_get_settings();
576
+ ?>
577
+ <div class="wrap">
578
+ <div class="icon32" id="icon-options-general"></div>
579
+ <h2><?php echo $settings_output['qts_page_title']; ?></h2>
580
+
581
+ <p><?php _e('If you activated previously the <a href="options-permalink.php">pretty permalinks</a>, in this section you can translate the <abbr title="en inglés, Universal Resource Locator">URLs</abbr> <strong>bases</strong> for <a href="http://codex.wordpress.org/Function_Reference/register_post_type#Arguments">public</a> post_types, categories, tags and taxonomies.', 'qts'); ?> </p>
582
+
583
+ <form action="options.php" method="post">
584
+ <?php
585
+ // upgrade notify
586
+ qts_upgrade();
587
+ // http://codex.wordpress.org/Function_Reference/settings_fields
588
+ settings_fields($settings_output['qts_option_name']);
589
+ // http://codex.wordpress.org/Function_Reference/do_settings_sections
590
+ do_settings_sections(__FILE__);
591
+ // rewrite rules
592
+ flush_rewrite_rules();
593
+ ?>
594
+
595
+ <p class="submit">
596
+ <input name="Submit" type="submit" class="button-primary" value="<?php esc_attr_e('Save Changes','qts'); ?>" />
597
+ </p>
598
+
599
+ </form>
600
+ </div><!-- wrap -->
601
+ <?php }
602
+
603
+
604
+
605
+ /**
606
+ * Validate input
607
+ *
608
+ * @package Qtranslate Slug
609
+ * @subpackage Settings
610
+ * @version 1.0
611
+ *
612
+ * @return array
613
+ */
614
+ function qts_validate_options($input) {
615
+
616
+ // for enhanced security, create a new empty array
617
+ $valid_input = array();
618
+
619
+ // collect only the values we expect and fill the new $valid_input array i.e. whitelist our option IDs
620
+
621
+ // get the settings sections array
622
+ $settings_output = qts_get_settings();
623
+
624
+ $options = $settings_output['qts_page_fields'];
625
+
626
+ // run a foreach and switch on option type
627
+ foreach ($options as $option):
628
+
629
+ switch ( $option['type'] ):
630
+ case 'text':
631
+ //switch validation based on the class!
632
+ switch ( $option['class'] ) {
633
+ //for numeric
634
+ case 'numeric':
635
+ //accept the input only when numeric!
636
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
637
+ $valid_input[$option['id']] = (is_numeric($input[$option['id']])) ? $input[$option['id']] : 'Expecting a Numeric value!';
638
+
639
+ // register error
640
+ if(is_numeric($input[$option['id']]) == FALSE) {
641
+ add_settings_error(
642
+ $option['id'], // setting title
643
+ QTS_PREFIX . '_txt_numeric_error', // error ID
644
+ __('Expecting a Numeric value! Please fix.', 'qts'), // error message
645
+ 'error' // type of message
646
+ );
647
+ }
648
+ break;
649
+
650
+ //for multi-numeric values (separated by a comma)
651
+ case 'multinumeric':
652
+ //accept the input only when the numeric values are comma separated
653
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
654
+
655
+ if($input[$option['id']] !=''){
656
+ // /^-?\d+(?:,\s?-?\d+)*$/ matches: -1 | 1 | -12,-23 | 12,23 | -123, -234 | 123, 234 | etc.
657
+ $valid_input[$option['id']] = (preg_match('/^-?\d+(?:,\s?-?\d+)*$/', $input[$option['id']]) == 1) ? $input[$option['id']] : __('Expecting comma separated numeric values','qts');
658
+ }else{
659
+ $valid_input[$option['id']] = $input[$option['id']];
660
+ }
661
+
662
+ // register error
663
+ if($input[$option['id']] !='' && preg_match('/^-?\d+(?:,\s?-?\d+)*$/', $input[$option['id']]) != 1) {
664
+ add_settings_error(
665
+ $option['id'], // setting title
666
+ QTS_PREFIX . '_txt_multinumeric_error', // error ID
667
+ __('Expecting comma separated numeric values! Please fix.','qts'), // error message
668
+ 'error' // type of message
669
+ );
670
+ }
671
+ break;
672
+
673
+ //for no html
674
+ case 'nohtml':
675
+ //accept the input only after stripping out all html, extra white space etc!
676
+ $input[$option['id']] = sanitize_text_field($input[$option['id']]); // need to add slashes still before sending to the database
677
+ $valid_input[$option['id']] = addslashes($input[$option['id']]);
678
+ break;
679
+
680
+ //for url
681
+ case 'url':
682
+ //accept the input only when the url has been sanited for database usage with esc_url_raw()
683
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
684
+ $valid_input[$option['id']] = esc_url_raw($input[$option['id']]);
685
+ break;
686
+
687
+ //for email
688
+ case 'email':
689
+ //accept the input only after the email has been validated
690
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
691
+ if($input[$option['id']] != ''){
692
+ $valid_input[$option['id']] = (is_email($input[$option['id']])!== FALSE) ? $input[$option['id']] : __('Invalid email', 'qts');
693
+ }elseif($input[$option['id']] == ''){
694
+ $valid_input[$option['id']] = __('This setting field cannot be empty! Please enter a valid email address.', 'qts');
695
+ }
696
+
697
+ // register error
698
+ if(is_email($input[$option['id']])== FALSE || $input[$option['id']] == '') {
699
+ add_settings_error(
700
+ $option['id'], // setting title
701
+ QTS_PREFIX . '_txt_email_error', // error ID
702
+ __('Please enter a valid email address.', 'qts'), // error message
703
+ 'error' // type of message
704
+ );
705
+ }
706
+ break;
707
+
708
+ // a "cover-all" fall-back when the class argument is not set
709
+ default:
710
+ // accept only a few inline html elements
711
+ $allowed_html = array(
712
+ 'a' => array('href' => array (),'title' => array ()),
713
+ 'b' => array(),
714
+ 'em' => array (),
715
+ 'i' => array (),
716
+ 'strong' => array()
717
+ );
718
+
719
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
720
+ $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup
721
+ $input[$option['id']] = wp_kses( $input[$option['id']], $allowed_html); // need to add slashes still before sending to the database
722
+ $valid_input[$option['id']] = addslashes($input[$option['id']]);
723
+ break;
724
+ }
725
+ break;
726
+
727
+ case "multi-text":
728
+ // this will hold the text values as an array of 'key' => 'value'
729
+ unset($textarray);
730
+
731
+ $text_values = array();
732
+ foreach ($option['choices'] as $k => $v ) {
733
+ // explode the connective
734
+ $pieces = explode("|", $v);
735
+
736
+ $text_values[] = $pieces[1];
737
+ }
738
+
739
+ foreach ($text_values as $v ) {
740
+
741
+ // Check that the option isn't empty
742
+ if (!empty($input[$option['id'] . '|' . $v])) {
743
+ // If it's not null, make sure it's sanitized, add it to an array
744
+ switch ($option['class']) {
745
+ // different sanitation actions based on the class create you own cases as you need them
746
+
747
+ //for numeric input
748
+ case 'numeric':
749
+ //accept the input only if is numberic!
750
+ $input[$option['id'] . '|' . $v]= trim($input[$option['id'] . '|' . $v]); // trim whitespace
751
+ $input[$option['id'] . '|' . $v]= (is_numeric($input[$option['id'] . '|' . $v])) ? $input[$option['id'] . '|' . $v] : '';
752
+ break;
753
+
754
+ case 'qts-slug':
755
+ // strip all html tags and white-space.
756
+ $type_ = end( explode('_', $option['id']) );
757
+ $input[$option['id'] . '|' . $v]= sanitize_title( sanitize_text_field( $input[$option['id'] . '|' . $v] ) );
758
+ $input[$option['id'] . '|' . $v]= addslashes($input[$option['id'] . '|' . $v]);
759
+ break;
760
+
761
+ // a "cover-all" fall-back when the class argument is not set
762
+ default:
763
+ // strip all html tags and white-space.
764
+ $input[$option['id'] . '|' . $v]= sanitize_text_field($input[$option['id'] . '|' . $v]); // need to add slashes still before sending to the database
765
+ $input[$option['id'] . '|' . $v]= addslashes($input[$option['id'] . '|' . $v]);
766
+ break;
767
+ }
768
+ // pass the sanitized user input to our $textarray array
769
+ $textarray[$v] = $input[$option['id'] . '|' . $v];
770
+
771
+ } else {
772
+ $textarray[$v] = '';
773
+ }
774
+ }
775
+ // pass the non-empty $textarray to our $valid_input array
776
+ if (!empty($textarray)) {
777
+ $valid_input[$option['id']] = $textarray;
778
+ }
779
+ break;
780
+
781
+ case 'textarea':
782
+ //switch validation based on the class!
783
+ switch ( $option['class'] ) {
784
+ //for only inline html
785
+ case 'inlinehtml':
786
+ // accept only inline html
787
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
788
+ $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup
789
+ $input[$option['id']] = addslashes($input[$option['id']]); //wp_filter_kses expects content to be escaped!
790
+ $valid_input[$option['id']] = wp_filter_kses($input[$option['id']]); //calls stripslashes then addslashes
791
+ break;
792
+
793
+ //for no html
794
+ case 'nohtml':
795
+ //accept the input only after stripping out all html, extra white space etc!
796
+ $input[$option['id']] = sanitize_text_field($input[$option['id']]); // need to add slashes still before sending to the database
797
+ $valid_input[$option['id']] = addslashes($input[$option['id']]);
798
+ break;
799
+
800
+ //for allowlinebreaks
801
+ case 'allowlinebreaks':
802
+ //accept the input only after stripping out all html, extra white space etc!
803
+ $input[$option['id']] = wp_strip_all_tags($input[$option['id']]); // need to add slashes still before sending to the database
804
+ $valid_input[$option['id']] = addslashes($input[$option['id']]);
805
+ break;
806
+
807
+ // a "cover-all" fall-back when the class argument is not set
808
+ default:
809
+ // accept only limited html
810
+ //my allowed html
811
+ $allowed_html = array(
812
+ 'a' => array('href' => array (),'title' => array ()),
813
+ 'b' => array(),
814
+ 'blockquote' => array('cite' => array ()),
815
+ 'br' => array(),
816
+ 'dd' => array(),
817
+ 'dl' => array(),
818
+ 'dt' => array(),
819
+ 'em' => array (),
820
+ 'i' => array (),
821
+ 'li' => array(),
822
+ 'ol' => array(),
823
+ 'p' => array(),
824
+ 'q' => array('cite' => array ()),
825
+ 'strong' => array(),
826
+ 'ul' => array(),
827
+ 'h1' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
828
+ 'h2' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
829
+ 'h3' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
830
+ 'h4' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
831
+ 'h5' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
832
+ 'h6' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ())
833
+ );
834
+
835
+ $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
836
+ $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup
837
+ $input[$option['id']] = wp_kses( $input[$option['id']], $allowed_html); // need to add slashes still before sending to the database
838
+ $valid_input[$option['id']] = addslashes($input[$option['id']]);
839
+ break;
840
+ }
841
+ break;
842
+
843
+ case 'select':
844
+ // check to see if the selected value is in our approved array of values!
845
+ $valid_input[$option['id']] = (in_array( $input[$option['id']], $option['choices']) ? $input[$option['id']] : '' );
846
+ break;
847
+
848
+ case 'select2':
849
+ // process $select_values
850
+ $select_values = array();
851
+ foreach ($option['choices'] as $k => $v) {
852
+ // explode the connective
853
+ $pieces = explode("|", $v);
854
+
855
+ $select_values[] = $pieces[1];
856
+ }
857
+ // check to see if selected value is in our approved array of values!
858
+ $valid_input[$option['id']] = (in_array( $input[$option['id']], $select_values) ? $input[$option['id']] : '' );
859
+ break;
860
+
861
+ case 'checkbox':
862
+ // if it's not set, default to null!
863
+ if (!isset($input[$option['id']])) {
864
+ $input[$option['id']] = null;
865
+ }
866
+ // Our checkbox value is either 0 or 1
867
+ $valid_input[$option['id']] = ( $input[$option['id']] == 1 ? 1 : 0 );
868
+ break;
869
+
870
+ case 'multi-checkbox':
871
+ unset($checkboxarray);
872
+ $check_values = array();
873
+ foreach ($option['choices'] as $k => $v ) {
874
+ // explode the connective
875
+ $pieces = explode("|", $v);
876
+
877
+ $check_values[] = $pieces[1];
878
+ }
879
+
880
+ foreach ($check_values as $v ) {
881
+
882
+ // Check that the option isn't null
883
+ if (!empty($input[$option['id'] . '|' . $v])) {
884
+ // If it's not null, make sure it's true, add it to an array
885
+ $checkboxarray[$v] = 'true';
886
+ }
887
+ else {
888
+ $checkboxarray[$v] = 'false';
889
+ }
890
+ }
891
+ // Take all the items that were checked, and set them as the main option
892
+ if (!empty($checkboxarray)) {
893
+ $valid_input[$option['id']] = $checkboxarray;
894
+ }
895
+ break;
896
+
897
+ endswitch;
898
+
899
+ endforeach;
900
+
901
+ return qts_sanitize_bases($valid_input);
902
+ }
903
+
904
+
905
+
906
+ /**
907
+ * Helper function for creating admin messages
908
+ *
909
+ * @package Qtranslate Slug
910
+ * @subpackage Settings
911
+ * @version 1.0
912
+ *
913
+ * src: http://www.wprecipes.com/how-to-show-an-urgent-message-in-the-wordpress-admin-area
914
+ *
915
+ * @param (string) $message The message to echo
916
+ * @param (string) $msgclass The message class
917
+ * @return echoes the message
918
+ */
919
+ function qts_show_msg($message, $msgclass = 'info') {
920
+ echo "<div id='message' class='$msgclass'>$message</div>";
921
+ }
922
+
923
+
924
+
925
+ /**
926
+ * Callback function for displaying admin messages
927
+ *
928
+ * @package Qtranslate Slug
929
+ * @subpackage Settings
930
+ * @version 1.0
931
+ *
932
+ * @return calls qts_show_msg()
933
+ */
934
+ function qts_admin_msgs() {
935
+ global $current_screen;
936
+
937
+ // check for our settings page - need this in conditional further down
938
+ $qts_settings_pg = isset($_GET['page']) ? strpos($_GET['page'], QTS_PAGE_BASENAME) : '';
939
+ // collect setting errors/notices: //http://codex.wordpress.org/Function_Reference/get_settings_errors
940
+ $set_errors = get_settings_errors();
941
+
942
+ //display admin message only for the admin to see, only on our settings page and only when setting errors/notices are returned!
943
+ if(current_user_can ('manage_options') && $qts_settings_pg !== false && !empty($set_errors)){
944
+
945
+ // have our settings succesfully been updated?
946
+ if($set_errors[0]['code'] == 'settings_updated' && isset($_GET['settings-updated'])){
947
+ qts_show_msg("<p>" . $set_errors[0]['message'] . "</p>", 'updated');
948
+
949
+ // have errors been found?
950
+ }else{
951
+ // there maybe more than one so run a foreach loop.
952
+ foreach($set_errors as $set_error){
953
+ // set the title attribute to match the error "setting title" - need this in js file
954
+ qts_show_msg("<p class='setting-error-message' title='" . $set_error['setting'] . "'>" . $set_error['message'] . "</p>", 'error');
955
+ }
956
+ }
957
+ }
958
+ }
959
+ add_action('admin_notices', 'qts_admin_msgs');
qtranslate-slug.php CHANGED
@@ -1,34 +1,64 @@
1
  <?php
2
  /*
3
  Plugin Name: qTranslate slug
4
- Plugin URI: http://wordpress.org/extend/plugins/qtranslate-slug/
5
  Description: Allows to define a slug for each language and some qTranslate bug fixes
6
- Version: 0.9
7
  Author: Carlos Sanz Garcia
8
- Author URI: http://codingsomethig.wordpress.com
9
 
10
- this plugin is a complete fork of the original qTranslate slug developed by Cimatti Consulting http://www.cimatti.it
 
11
 
12
  --------------------------------------------------------------------------------------------------------
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  version 0.9
16
- + some wordpress qTranslate bug fixes
17
- + adds a javascript solution for qTranslate Nav Menus
18
 
19
  version 0.8
20
- + added support por Categories
21
- + added support por Tags
22
- + added support por Taxonomies
23
- + added support por Custom Post Types
24
 
25
- version 0.7 enhanced by Zapo (http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499)
26
- + added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit
27
 
28
  Version 0.5 and 0.6 enhanched by Marco Del Percio
29
 
30
  --------------------------------------------------------------------------------------------------------
31
 
 
 
 
 
 
 
 
 
32
  This program is free software; you can redistribute it and/or
33
  modify it under the terms of the GNU General Public License
34
  as published by the Free Software Foundation; either version 2
@@ -45,1481 +75,2309 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
45
 
46
 
47
  The full copy of the GNU General Public License is available here: http://www.gnu.org/licenses/gpl.txt
48
-
49
  */
50
 
51
- /* Notes
52
- * fb() is a function defined by the WP-FirePHP plugin <http://wordpress.org/extend/plugins/wp-firephp/>, that allows debug using Firefox, Firebug and FirePHP.
53
- *
54
- * TODO:
55
-
56
- * admin options page for setup the taxonomies names
57
- * change the database system ( post meta ), without installing tables
58
- * generate translated slug automatically from the translated title
59
- * check if the slug is already used, and add a progressive number in this case
60
- * force the use of the translated slug if defined
61
- * force to show a page/post only at the correct URL
62
- * try to redirect from a wrong URL to a correct URL
63
- * keep track of renamed slugs, redirecting from old to new slugs
64
- * translate categories and tags slugs.
65
- */
66
-
67
- // Codes used in the database to indicate posts, pages, categories and tags.
68
- $qts_post_types = array(
69
- 'QTS_POST' => 1,
70
- 'QTS_PAGE' => 2,
71
- 'QTS_CAT' => 3,
72
- 'QTS_TAG' => 4,
73
- 'QTS_TAX' => 5
74
- );
75
- foreach ($qts_post_types as $type => $id) define($type, $id);
76
 
 
77
 
78
- /**
79
- * Variable used to override the language
80
- */
81
- $qts_use_language = null;
82
 
83
- /**
84
- * Array of translated versions of the current url
85
- */
86
- $qts_self_url = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  /**
89
- * Function invoked during the installation of the module. It creates or updates the tables
 
 
90
  */
91
- function qTranslateSlug_install(){
92
- global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
- $table_name = $wpdb->prefix.'qtranslate_slug';
95
- require_once(ABSPATH.'wp-admin/includes/upgrade.php');
96
 
97
- $collate = '';
98
- if($wpdb->supports_collation()) {
99
- if(!empty($wpdb->charset)) $collate = "DEFAULT CHARACTER SET $wpdb->charset";
100
- if(!empty($wpdb->collate)) $collate .= " COLLATE $wpdb->collate";
101
- }
102
-
103
- $sql = 'CREATE TABLE IF NOT EXISTS '.$table_name.' (
104
- qts_type TINYINT(3) UNSIGNED NOT NULL,
105
- qts_id BIGINT(20) UNSIGNED NOT NULL,
106
- qts_lang VARCHAR(6) NOT NULL,
107
- qts_slug VARCHAR(200) NOT NULL,
108
- PRIMARY KEY id_lang (qts_type, qts_id, qts_lang),
109
- KEY post_name_lang (qts_slug, qts_type, qts_lang)
110
- );' ;
111
- $wpdb->query($sql);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
- register_activation_hook( __FILE__ , 'qTranslateSlug_install');
114
-
115
 
116
 
117
 
118
- function qTranslateSlug_get_custom_taxonomy_slug($taxonomy) {
119
- global $taxonomies_slugs, $q_config, $qts_use_language;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- if(!function_exists('qTranslateSlug_term_link') || !isset($taxonomies_slugs)) return $taxonomy;
122
 
123
- $lang = ($qts_use_language === null) ? $q_config['language'] : $qts_use_language;
124
 
125
- if (is_array($taxonomies_slugs[$taxonomy])) {
126
- return $taxonomies_slugs[$taxonomy][$lang];
127
- } else {
128
- return $taxonomy;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
- }
131
-
132
-
133
-
134
- /**
135
- * Function called when query parameters are processed by Wordpress.
136
- *
137
- * @param $q query parameters
138
- * @return array() $q processed
139
- */
140
- function qTranslateSlug_filter_request($q){
141
- global $q_config, $wpdb, $qts_use_language, $qts_self_url, $qts_reset_self_url, $taxonomies_slugs ;
142
-
143
- if ($qts_use_language !== null){
144
- $lang = (string) $qts_use_language;
145
- } else {
146
- if (!isset($q_config['language'])){
147
- return $q;
148
- }
149
- $lang = (string) $q_config['language'];
150
  }
151
-
152
- $new_q = $q;
153
-
154
- // SEARCH TAXONOMIES
155
- $args=array(
156
- 'public' => true,
157
- '_builtin' => false
158
- );
159
- $output = 'object';
160
- $operator = 'and';
161
- $taxonomies = get_taxonomies($args, $output, $operator);
162
-
163
- foreach ($taxonomies as $taxonomy ) {
164
- if (isset($q[$taxonomy->name])) {
165
- $type = QTS_TAX;
166
- $slug = $q[$taxonomy->name];
167
- $param = 'term_id';
168
- $get_link = 'qTranslateSlug_term_link';
169
- $taxonomy_ = $taxonomy->name;
170
- //unset($new_q[$taxonomy->name]);
171
- }
172
  }
173
 
174
- if (isset($type) && $type == QTS_TAX) {
175
- // is taxonomy
176
- } else if (isset($q['post_type']) && !is_admin() ) {
177
- $id = qTranslateSlug_get_post_type_by_path($q['name'], $lang, $q['post_type']);
178
- if ($id) {
179
- $q = $new_q;
180
- $q['page_id']=$id;
181
- $get_link = 'get_post_permalink';
182
- //$post_ = get_post();
183
-
184
- //$q['name'] = qTranslateSlug_get_post_name($id);
185
- //$q['name'] = 'pinord-do-penedes/la-zona';
186
- /*
187
- print_r($post_);
188
- exit;
189
- */
190
- }
191
- } else if (isset($q['name'])) {
192
- $type = QTS_POST;
193
- $slug = $q['name'];
194
- $param = 'p';
195
- $get_link = 'get_permalink';
196
- unset($new_q['name']);
197
- } else if (isset($q['pagename'])) {
198
- //$type = QTS_PAGE;
199
- //$slug = $q['pagename'];
200
- //$param = 'page_id';
201
- $id = qTranslateSlug_get_post_type_by_path($q['pagename'], $lang);
202
- if ($id) {
203
- unset($new_q['pagename']);
204
- $q = $new_q;
205
- $q['page_id']=$id;
206
- $get_link = 'get_page_link';
207
- }
208
- } else if (isset($q['category_name'])) {
209
- $type = QTS_CAT;
210
- $taxonomy_ = 'category';
211
- $slug = $q['category_name'];
212
- $param = 'cat';
213
- $get_link = 'get_category_link';
214
- unset($new_q['category_name']);
215
- } else if (isset($q['tag'])) {
216
- $type = QTS_TAG;
217
- $taxonomy_ = 'post_tag';
218
- $slug = $q['tag'];
219
- $param = 'tag_id';
220
- $get_link = 'get_tag_link';
221
- unset($new_q['tag']);
222
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
- if (isset($type)){
225
- $slugs = explode('/',$slug);
226
- $slug = array_pop($slugs);
227
-
228
- $query = 'SELECT qts_id FROM '.$wpdb->prefix.'qtranslate_slug WHERE \''.$wpdb->escape($slug).'\' = qts_slug AND '.$type.' = qts_type AND \''.$wpdb->escape($lang).'\' = qts_lang';
229
- @ $id = $wpdb->get_var($query);
230
-
231
- if ($id) {
232
- $q = $new_q;
233
-
234
- if (($type == QTS_TAX || $type == QTS_CAT || $type == QTS_TAG )) {
235
- $term_ = &get_term($id, $taxonomy_);
236
 
237
- switch ($type) {
238
- case QTS_CAT:
239
- $q['category_name'] = $term_->slug;
240
- break;
241
- case QTS_TAG:
242
- $q['tag'] = $term_->slug;
243
- break;
244
- default:
245
- $q[$taxonomy_] = $term_->slug;
246
- break;
247
  }
248
- } else {
249
- $q[$param]=$id;
250
  }
251
  }
252
- }
253
-
254
- if (isset($get_link) && $id && (!$qts_self_url)){
255
- $old_qts_use_language = $qts_use_language;
256
- foreach($q_config['enabled_languages'] as $l) {
257
- global $qts_self_url;
258
- $qts_use_language = $l;
259
- if (isset($type) && $type == QTS_TAX) {
260
- $link = rtrim(get_option('home'),"/"). '/'. qTranslateSlug_get_custom_taxonomy_slug($term_->taxonomy) . "/" . $term_->slug . "/";
261
- $qts_self_url[$l] = call_user_func($get_link, $link, $term_, $taxonomy_) . qTranslateSlug_putGetVars();
262
- } else if ( isset($type) && ( $type == QTS_TAX || $type == QTS_TAG ) ) {
263
- $qts_self_url[$l] = call_user_func($get_link, $term_) . qTranslateSlug_putGetVars();
264
- } else {
265
- $qts_self_url[$l] = call_user_func($get_link, $id) . qTranslateSlug_putGetVars();
266
- }
267
- }
268
- $qts_use_language = $old_qts_use_language;
269
  }
270
 
271
- return $q;
272
- }
273
- add_filter('request','qTranslateSlug_filter_request');
274
-
275
 
 
 
 
 
 
 
 
 
276
 
277
- /**
278
- * Returns the link to the current page in the desired language
279
- *
280
- * @param $lang the code of the desired language
281
- * @return the link for the current page in that language
282
- */
283
- function qTranslateSlug_getSelfUrl($lang){
284
- //global $qts_self_url, $wp_query, $wpdb;
285
- global $q_config, $qts_self_url;
286
-
287
- if (!isset($qts_self_url[$lang])) {
288
- $qts_self_url[$lang] = qTranslateSlug_convertURL(esc_url($q_config['url_info']['url']), $lang) . qTranslateSlug_putGetVars();
289
- }
290
-
291
- return $qts_self_url[$lang];
292
- }
293
-
294
-
295
-
296
-
297
- /**
298
- * Converts an url in another language.
299
- *
300
- * This corresponds to qtrans_convertURL, but for now it doesn't check if the url contains translatable slugs.
301
- * If you need a translation of the current page, you should use qTranslateSlug_getSelfUrl($lang).
302
- * If you need the translation for a specific page or post id, you should use get_page_link($id) or get_permalink($id).
303
- *
304
- * I extracted qTranslateSlug_urlAddLang() from this function if you just need to add language and home path to a clean relative url.
305
- *
306
- * @param $url
307
- * @param $lang
308
- * @param $forceadmin
309
- * @return unknown_type
310
- */
311
- function qTranslateSlug_convertURL($url='', $lang='', $forceadmin = false) {
312
- if ( defined('WP_ADMIN') && !$forceadmin) return $url;
313
- global $q_config;
314
-
315
- if($lang=='') $lang = $q_config['language'];
316
- //if($url=='') $url = qTranslateSlug_getSelfUrl($lang);
317
- if($url=='') $url = esc_url($q_config['url_info']['url']);
318
- if(!qtrans_isEnabled($lang)) return "";
319
-
320
- // & workaround
321
- $url = str_replace('&amp;','&',$url);
322
- $url = str_replace('&#038;','&',$url);
323
-
324
- // check if it's an external link
325
- $urlinfo = qtrans_parseURL($url);
326
- $home = rtrim(get_option('home'),"/");
327
- if($urlinfo['host']!='') {
328
- // check for already existing pre-domain language information
329
- if($q_config['url_mode'] == QT_URL_DOMAIN && preg_match("#^([a-z]{2}).#i",$urlinfo['host'],$match)) {
330
- if(qtrans_isEnabled($match[1])) {
331
- // found language information, remove it
332
- $url = preg_replace("/".$match[1]."\./i","",$url, 1);
333
- // reparse url
334
- $urlinfo = qtrans_parseURL($url);
335
- }
336
- }
337
 
338
- if($q_config['url_mode'] == QT_URL_TLD && preg_match("/\.([a-z]{2,3})$/i",$urlinfo['host'],$match)) {
339
-
340
- //if(qtrans_isEnabled($match[1])) {
 
341
 
342
- $tld = (!empty($q_config['language_tldcode'][$lang])) ? $q_config['language_tldcode'][$lang] : $lang;
 
343
 
344
- // found language information, replace it
345
- $url = preg_replace("/\.".$match[1]."/i",'.'.$tld, $url, 1);
346
-
347
- // reparse url
348
- $urlinfo = qtrans_parseURL($url);
349
-
350
- //}
351
  }
352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
 
354
- if(substr($url,0,strlen($home))!=$home) {
355
- return $url;
356
- }
357
- // strip home path
358
- $url = substr($url,strlen($home));
359
- } else {
360
- // relative url, strip home path
361
- $homeinfo = qtrans_parseURL($home);
362
- if($homeinfo['path']==substr($url,0,strlen($homeinfo['path']))) {
363
- $url = substr($url,strlen($homeinfo['path']));
364
- }
365
  }
366
 
367
- // check for query language information and remove if found
368
- if(preg_match("#(&|\?)lang=([^&\#]+)#i",$url,$match) && qtrans_isEnabled($match[2])) {
369
- $url = preg_replace("#(&|\?)lang=".$match[2]."&?#i","$1",$url);
 
 
 
 
 
 
 
 
 
 
 
 
370
  }
371
 
372
- // remove any slashes out front
373
- $url = ltrim($url,"/");
374
 
375
- // remove any useless trailing characters
376
- $url = rtrim($url,"?&");
377
 
378
- // reparse url without home path
379
- $urlinfo = qtrans_parseURL($url);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
 
381
- // check if its a link to an ignored file type
382
- $ignore_file_types = preg_split('/\s*,\s*'.'/', strtolower($q_config['ignore_file_types']));
383
- $pathinfo = pathinfo($urlinfo['path']);
384
- if(isset($pathinfo['extension']) && in_array(strtolower($pathinfo['extension']), $ignore_file_types)) {
385
- return $home."/".$url;
 
 
 
 
386
  }
387
 
388
- return qTranslateSlug_urlAddLang($url, $lang, $urlinfo, $home);
389
- }
390
-
391
-
392
-
393
- /**
394
- * Adds home path and language to an already cleaned URL.
395
- * It doesn't reparse the url, and supposes $url is a clean relative url.
396
- * You may pass $urlinfo and $home if you have already them.
397
- *
398
- * @param $url the relative url
399
- * @param $lang the desired language
400
- * @param $urlinfo result of qtrans_parseURL($url)
401
- * @param $home result of rtrim(get_option('home'),"/")
402
- * @return the absolute url with language informations
403
- */
404
- function qTranslateSlug_urlAddLang($url, $lang='', $urlinfo='', $home='') {
405
- global $q_config;
406
 
407
- if($lang=='') $lang = $q_config['language'];
408
- if($urlinfo=='') $urlinfo = qtrans_parseURL($url);
409
- if($home=='') $home = rtrim(get_option('home'),"/");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
 
411
 
412
- switch($q_config['url_mode']) {
413
- case QT_URL_PATH: // pre url
414
- // might already have language information
415
- if(preg_match("#^([a-z]{2})/#i",$url,$match)) {
416
- if(qtrans_isEnabled($match[1])) {
417
- // found language information, remove it
418
- $url = substr($url, 3);
419
- }
420
- }
421
- //if(!$q_config['hide_default_language']||$lang!=$q_config['default_language']) $url = $lang."/".$url;
422
- //Check for older version of qtranslate without hide_default_language option
423
- if ( ($lang!=$q_config['default_language']) || (isset($q_config['hide_default_language']) && (!$q_config['hide_default_language']))) $url = $lang."/".$url;
424
- break;
425
- case QT_URL_DOMAIN: // pre domain
426
- //if(!$q_config['hide_default_language']||$lang!=$q_config['default_language']) $home = preg_replace("#//#","//".$lang.".",$home,1);
427
- //Check for older version of qtranslate without hide_default_language option
428
- if ( ($lang!=$q_config['default_language']) || (isset($q_config['hide_default_language']) && (!$q_config['hide_default_language']))) $home = preg_replace("#//#","//".$lang.".",$home,1);
429
- break;
430
- case QT_URL_TLD: // tld domain
431
-
432
- if($lang !=$q_config['default_language']) {
433
-
434
- $tld = (!empty($q_config['language_tldcode'][$lang])) ? $q_config['language_tldcode'][$lang] : $lang;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
 
436
- //$home = preg_replace("#^(http://[^/.]+)(\.?)([a-z]{0,3})#", '$1.'.$tld, $home, 1);
437
 
438
- if (preg_match("/\.([a-z]{2,3})$/i",$home,$match)) {
439
- $home = str_replace($match[0], ".".$tld, $home);
440
- }
441
- }
442
- break;
443
-
444
-
445
- default: // query
446
- //Check for older version of qtranslate without hide_default_language option
447
- if ( ($lang!=$q_config['default_language']) || (isset($q_config['hide_default_language']) && (!$q_config['hide_default_language']))) {
448
- if(strpos($url,'?')===false) {
449
- $url .= '?';
450
  } else {
451
- $url .= '&';
452
  }
453
- $url .= "lang=".$lang;
454
- }
 
 
 
 
455
  }
456
 
457
- // see if cookies are activated
458
- if(!$q_config['cookie_enabled'] && !$q_config['url_info']['internal_referer'] && $urlinfo['path'] == '' && $lang == $q_config['default_language'] && $q_config['language'] != $q_config['default_language'] && (isset($q_config['hide_default_language'])?$q_config['hide_default_language']:true)) {
459
- // :( now we have to make unpretty URLs
460
- $url = preg_replace("#(&|\?)lang=".$match[2]."&?#i","$1",$url);
461
- if(strpos($url,'?')===false) {
462
- $url .= '?';
 
 
 
 
 
 
 
 
 
 
 
 
463
  } else {
464
- $url .= '&';
465
  }
466
- $url .= "lang=".$lang;
 
 
 
 
 
 
 
 
 
 
 
467
  }
468
 
469
- // &amp; workaround
470
- $complete = str_replace('&','&amp;',$home."/".$url);
471
 
472
- return $complete;
473
- }
474
-
475
-
476
-
477
- /**
478
- * Hide auttomatically the wordpress slug blog in edit posts page
479
- */
480
- function qTranslateSlug_remove_slug_box() {
481
 
482
- function qTranslateSlug_remove_slug_block() {
483
- echo '<!-- QTS remove slug box -->
484
- <style type="text/css" media="screen">
485
- #edit-slug-box { display: none !important}
486
- </style>';
 
 
 
 
 
 
 
 
487
  }
488
 
489
- if (is_admin())
490
- add_action('admin_head', 'qTranslateSlug_remove_slug_block', 900);
491
 
492
- }
493
-
494
-
495
-
496
- /**
497
- * Activates filters defined by this module
498
- */
499
- add_filter('post_type_link', 'qTranslateSlug_post_type_link', 0, 4);
500
- add_filter('page_link', 'qTranslateSlug_page_link', 0, 2);
501
- add_filter('post_link', 'qTranslateSlug_post_link', 0, 3);
502
- add_filter('term_link', 'qTranslateSlug_term_link', 600 , 3);
503
- add_action('admin_menu', 'qTranslateSlug_remove_slug_box');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
 
 
505
 
506
- /**
507
- * Disables qtranslate filter for the link managed by this module
508
- */
509
- function qTranslateSlug_remove_qtrans_filters() {
510
- remove_filter('page_link', 'qtrans_convertURL');
511
- remove_filter('post_link', 'qtrans_convertURL');
512
- remove_filter('category_link', 'qtrans_convertURL');
513
- remove_filter('tag_link', 'qtrans_convertURL');
514
- }
515
- add_action('plugins_loaded','qTranslateSlug_remove_qtrans_filters');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
 
517
- //TODO: Links that may have to be checked
518
- //add_filter('category_feed_link', 'qtrans_convertURL');
519
- //add_filter('the_permalink', 'qtrans_convertURL');
520
- //add_filter('feed_link', 'qtrans_convertURL');
521
- //add_filter('post_comments_feed_link', 'qtrans_convertURL');
522
- //add_filter('tag_feed_link', 'qtrans_convertURL');
523
- //add_filter('esc_url', 'qtrans_convertURL');
524
 
 
 
525
 
 
526
 
527
- /**
528
- * Filter that translates the slug parts in a page link
529
- *
530
- * @param $link the link for the page generated by Wordpress
531
- * @param $id the id of the page
532
- * @return the link translated
533
- */
534
- function qTranslateSlug_page_link($link, $id){
535
- //$fb = function_exists('fb');
536
- //$fb && fb($link,'start $link') && fb($id, 'start $id');
537
- global $wpdb,$q_config, $qts_use_language;
538
- $lang = ($qts_use_language === null)?$q_config['language']:$qts_use_language;
539
-
540
- $home = rtrim(get_option('home'),"/");
541
- $link = substr($link,strlen($home));
542
- $link = ltrim($link,"/");
543
- $link = rtrim($link,"?&");
544
 
545
- $urlinfo = qtrans_parseURL($link);
 
 
 
 
546
 
547
- if ($urlinfo['query']){
548
- return qTranslateSlug_urlAddLang($link, $lang, $urlinfo, $home);
549
- }
550
-
551
- $linkParts = explode('/', $link);
552
- $i = count($linkParts) - 1;
553
-
554
- if ($linkParts[$i] === ''){
555
- $i--;
556
- }
557
-
558
- do {
559
- $id = (int)$id;
560
- $query = 'SELECT post_parent, qts_slug
561
- FROM '.$wpdb->posts.' p
562
- LEFT JOIN ( SELECT *
563
- FROM '.$wpdb->prefix.'qtranslate_slug
564
- WHERE '.QTS_PAGE.' = qts_type
565
- AND '.$id.' = qts_id
566
- AND \''.$wpdb->escape($lang).'\' = qts_lang
567
- ) qts ON p.ID = qts.qts_id
568
- WHERE '.$id.' = ID';
569
- @ $res = $wpdb->get_row($query,ARRAY_A);
570
- //$fb && fb($query, '$query') && fb($res, '$res');
571
-
572
- if (!$res) {
573
- break;
574
- }
575
-
576
- $parent = $res['post_parent'];
577
- $slug = $res['qts_slug'];
578
-
579
- if ($slug) {
580
- $linkParts[$i] = $slug;
581
- }
582
-
583
- if ((!$parent) || ($parent == $id)){
584
- break;
585
- }
586
-
587
- $id = $parent;
588
- $i--;
589
- } while ($i >= 0);
590
-
591
- $link = implode('/',$linkParts);
592
-
593
- $ret = qTranslateSlug_urlAddLang($link, $lang, $urlinfo, $home);
594
- //$fb && fb($link, 'end $link') && fb($id, 'end $id') && fb($ret,'return');
595
-
596
- return $ret;
597
- }
598
 
 
 
599
 
 
 
 
600
 
601
- /**
602
- * Filter that translates the slug parts in a page link
603
- *
604
- * @param $link the link for the page generated by Wordpress
605
- * @param $id the id of the page
606
- * @return the link translated
607
- */
608
-
609
- //$post_link, $post, $leavename, $sample
610
- function qTranslateSlug_post_type_link($link, $post, $leavename, $sample){
611
- global $wpdb,$q_config, $qts_use_language, $custom_post_types_slugs;
612
 
613
- $id = $post->ID;
614
- $lang = ($qts_use_language === null) ? $q_config['language'] : $qts_use_language;
615
-
616
- $home = rtrim(get_option('home'),"/");
617
- $link = substr($link,strlen($home));
618
- $link = ltrim($link,"/");
619
- $link = rtrim($link,"?&");
620
- $urlinfo = qtrans_parseURL($link);
621
-
622
- if ($urlinfo['query']){
623
- return qTranslateSlug_urlAddLang($link, $lang, $urlinfo, $home);
624
- }
625
-
626
- $linkParts = explode('/', $link);
627
-
628
- if ($custom_post_types_slugs !== null && !is_admin()) {
629
-
630
- foreach ($linkParts as $key => $part) {
631
- if (in_array($part, $custom_post_types_slugs[$post->post_type])) {
632
- $linkParts[$key] = $custom_post_types_slugs[$post->post_type][$lang];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
633
  }
634
- }
635
- }
636
-
637
- $i = count($linkParts) - 1;
638
-
639
- if ($linkParts[$i] === '') {
640
- $i--;
641
- }
642
-
643
- do {
644
- $id = (int)$id;
645
- $query = 'SELECT post_parent, qts_slug
646
- FROM '.$wpdb->posts.' p
647
- LEFT JOIN ( SELECT *
648
- FROM '.$wpdb->prefix.'qtranslate_slug
649
- WHERE '.QTS_PAGE.' = qts_type
650
- AND '.$id.' = qts_id
651
- AND \''.$wpdb->escape($lang).'\' = qts_lang
652
- ) qts ON p.ID = qts.qts_id
653
- WHERE '.$id.' = ID';
654
- @ $res = $wpdb->get_row($query,ARRAY_A);
655
- //$fb && fb($query, '$query') && fb($res, '$res');
656
-
657
- if (!$res) {
658
- break;
659
- }
660
-
661
- $parent = $res['post_parent'];
662
- $slug = $res['qts_slug'];
663
-
664
- if ($slug) {
665
- $linkParts[$i] = $slug;
666
- }
667
-
668
- if ((!$parent) || ($parent == $id)){
669
- break;
670
- }
671
-
672
- $id = $parent;
673
- $i--;
674
- } while ($i >= 0);
675
-
676
- $link = implode('/',$linkParts);
677
-
678
- $ret = qTranslateSlug_urlAddLang($link, $lang, $urlinfo, $home);
679
- //$fb && fb($link, 'end $link') && fb($id, 'end $id') && fb($ret,'return');
680
-
681
- return $ret;
682
- }
683
-
684
-
685
-
686
- /**
687
- * Filter that translates the slug in a post link
688
- *
689
- * @param $link the link generated by wordpress
690
- * @param $post the post data
691
- * @param $leavename parameter used by get_permalink. Whether to keep post name or page name.
692
- * @return the link translated
693
- */
694
- function qTranslateSlug_post_link($link, $post, $leavename){
695
- global $wpdb, $q_config, $qts_use_language;
696
-
697
- //$fb = function_exists('fb');
698
- //$fb && fb($link, 'initial $link') && fb($post, '$post');
699
-
700
- $lang = ($qts_use_language === null)?$q_config['language']:$qts_use_language;
701
 
702
- $permalink = get_option('permalink_structure');
703
 
704
- $home = rtrim(get_option('home'),"/");
705
 
706
- $trans_slug = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
 
708
- if ((!empty($post->ID)) && ('' != $permalink) && !in_array($post->post_status, array('draft', 'pending')) ) {
709
- $query = $wpdb->prepare(
710
- " SELECT qts_slug
711
- FROM {$wpdb->prefix}qtranslate_slug
712
- WHERE %d = qts_type
713
- AND %d = qts_id
714
- AND %s = qts_lang",
715
- QTS_POST, $post->ID, $lang);
716
- @$trans_slug = $wpdb->get_var($query);
717
- //$fb && fb($query,'$query') && fb($trans_slug,'$trans_slug');
 
 
 
 
 
718
  }
719
 
720
- if ($trans_slug !== null) {
721
- $unixtime = strtotime($post->post_date);
722
-
723
- $rewritecode = array(
724
- '%year%',
725
- '%monthnum%',
726
- '%day%',
727
- '%hour%',
728
- '%minute%',
729
- '%second%',
730
- $leavename? '' : '%postname%',
731
- '%post_id%',
732
- '%category%',
733
- '%author%',
734
- $leavename? '' : '%pagename%',
735
- );
736
-
737
- //TODO: translate category slug
738
- $category = '';
739
- if ( strpos($permalink, '%category%') !== false ) {
740
- $cats = get_the_category($post->ID);
741
- if ( $cats ) {
742
- usort($cats, '_usort_terms_by_ID'); // order by ID
743
- $category = $cats[0]->slug;
744
- if ( $parent = $cats[0]->parent )
745
- $category = get_category_parents($parent, false, '/', true) . $category;
746
- }
747
- // show default category in permalinks, without
748
- // having to assign it explicitly
749
- if ( empty($category) ) {
750
- $default_category = get_category( get_option( 'default_category' ) );
751
- $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
752
  }
753
  }
754
-
755
- $author = '';
756
- if ( strpos($permalink, '%author%') !== false ) {
757
- $authordata = get_userdata($post->post_author);
758
- $author = $authordata->user_nicename;
 
 
 
 
 
 
 
759
  }
760
 
761
- $date = explode(" ",date('Y m d H i s', $unixtime));
762
- $rewritereplace = array(
763
- $date[0],
764
- $date[1],
765
- $date[2],
766
- $date[3],
767
- $date[4],
768
- $date[5],
769
- $trans_slug,
770
- $post->ID,
771
- $category,
772
- $author,
773
- $trans_slug,
774
- );
775
- $link = user_trailingslashit(str_replace($rewritecode, $rewritereplace, $permalink), 'single');
776
- } else {
777
- $link = substr($link, strlen($home));
778
  }
779
- $link = ltrim($link, '/');
780
- $link = qTranslateSlug_urlAddLang($link, $lang,'', $home);
781
- //$fb && fb($link,'new $link');
782
- return $link;
783
- }
784
-
785
- function getParentTermsSlugTranslation($link, $term, $lang, $taxonomy) {
786
- global $wpdb;
787
-
788
- $cat_id = $term->term_id;
789
- $mycategory = $term;
790
-
791
- $term_type = qTranslateSlug_get_term_type($taxonomy);
792
-
793
- $category_parent_id = $mycategory->parent;
794
- $category_parent_id = (int)$category_parent_id;
795
- if($category_parent_id != 0) {
796
- $parentCategory = &get_term($category_parent_id, $taxonomy);
797
- $parentCategorySlug = $parentCategory->slug;
798
- if ($parentCategorySlug != '') {
799
- $query = $wpdb->prepare(
800
- "SELECT qts_slug
801
- FROM {$wpdb->prefix}qtranslate_slug
802
- WHERE %d = qts_type
803
- AND %d = qts_id
804
- AND %s = qts_lang",
805
- $term_type, $category_parent_id, $lang);
806
- @$trans_slug = $wpdb->get_var($query);
807
- if ($trans_slug !== null) {
808
- $link = str_replace($parentCategorySlug, $trans_slug, $link);
809
- }
810
-
811
- $parentParentCatId = (int)$parentCategory->parent;
812
- if($parentParentCatId != 0) {
813
- return getParentTermsSlugTranslation($link, $parentCategory, $lang, $taxonomy);
814
- }
815
- else {
816
- return $link;
817
- }
818
- }
819
- else {
820
- return $link;
821
- }
822
- }
823
- else {
824
- return $link;
825
- }
826
- }
827
-
828
- function qTranslateSlug_term_link($link, $term, $taxonomy) {
829
 
830
- global $wpdb, $q_config, $qts_use_language, $wp_query, $taxonomies_slugs;
831
-
832
- $id = $term->term_id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
833
 
834
- $lang = ($qts_use_language === null)?$q_config['language']:$qts_use_language;
835
-
836
- $home = rtrim(get_option('home'),"/");
837
 
838
- $term_type = qTranslateSlug_get_term_type($taxonomy);
839
-
840
- //Marco INIZIO
841
- $trans_slug = null;
842
- $permalink = get_option('permalink_structure');
843
-
844
- $category_id = '';
845
- $category_slug = '';
846
-
847
- $mycategory = $term;
848
- $category_slug = $term->slug;
849
- $category_id = $id;
850
-
851
- if (($category_id != '') && ('' != $permalink) && ($category_slug != '')) {
852
- $query = $wpdb->prepare(
853
- " SELECT qts_slug
854
- FROM {$wpdb->prefix}qtranslate_slug
855
- WHERE %d = qts_type
856
- AND %d = qts_id
857
- AND %s = qts_lang",
858
- $term_type, $category_id, $lang);
859
- @$trans_slug = $wpdb->get_var($query);
860
- }
861
 
862
- $link = ltrim(substr($link, strlen($home)), '/');
863
-
864
- if ($trans_slug !== null) {
865
- $link = str_replace($category_slug, $trans_slug, $link);
866
- }
867
-
868
- $link = getParentTermsSlugTranslation($link, $term, $lang, $taxonomy);
869
 
870
- //print_r(qTranslateSlug_urlAddLang($link, $lang, '', $home));
871
 
872
- return qTranslateSlug_urlAddLang($link, $lang, '', $home);
873
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
874
 
875
- function qTranslateSlug_putGetVars() {
876
- //global $current_user;
877
- $vars_ = array();
 
878
 
879
- if (isset($_GET) && count($_GET) > 0) {
 
 
 
 
 
 
 
 
 
 
 
880
 
881
- foreach ($_GET as $name => $value) {
882
- if (is_array($value)) {
883
- foreach ($value as $value_) {
884
- $vars_[] = $name. '%5B%5D=' . $value_;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
885
  }
886
- } else {
887
- if ($name != 'q' && $name != 's') {
888
- $vars_[] = $name . '=' . $value;
 
 
 
 
 
 
889
  }
890
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
891
  }
 
 
892
  }
893
 
894
- $vars_ = apply_filters('qtranslateslug_putgetvars', $vars_);
895
 
896
- if (!empty($vars_)) {
897
- $ret = (isset($_GET['s'])) ? '&amp;' : '?';
898
- return $ret . implode('&amp;', $vars_);
899
- } else {
900
- return '';
901
- }
902
- }
 
 
 
 
 
 
 
 
 
 
 
 
903
 
904
- /**
905
- * Returns the id of the page with the specified path.
906
- *
907
- * @param $page_path the path
908
- * @param $lang optional, the desired language
909
- * @return id of the page
910
- */
911
- function qTranslateSlug_get_post_type_by_path($page_path, $lang = '', $post_type = 'page') {
912
- global $wpdb, $q_config, $qts_use_language, $custom_post_types_slugs;
913
- //$fb = function_exists('fb');
914
- if ($lang == ''){
915
- $lang = ($qts_use_language === null)?$q_config['language']:$qts_use_language;
916
- }
917
- $page_path = rawurlencode(urldecode($page_path));
918
- $page_path = str_replace('%2F', '/', $page_path);
919
- $page_path = str_replace('%20', ' ', $page_path);
920
- $page_paths = '/' . trim($page_path, '/');
921
- $page_paths = explode('/', $page_paths);
922
- $spage_paths = array();
923
- $full_path = '';
924
- foreach( (array) $page_paths as $pathdir){
925
- $pathdir = sanitize_title($pathdir);
926
- if ($pathdir !== ''){
927
- $spage_paths[] = $pathdir;
928
- $full_path .= '/'.$pathdir;
929
- }
930
- }
931
- $leaf_path = array_pop($spage_paths);
932
-
933
- /* This makes invalid the default slug, if it was defined a slug in the desired language.
934
- * However, without other modifications, the default slug is found anyway by wordpress, so we can find it here.
935
- $query = $wpdb->prepare(
936
- " (SELECT ID, qts_slug AS post_name, post_parent
937
- FROM {$wpdb->posts}, {$wpdb->prefix}qtranslate_slug
938
- WHERE %s = qts_slug
939
- AND %d = qts_type
940
- AND %s = qts_lang
941
- AND qts_id = ID)
942
- UNION (SELECT ID, post_name, post_parent
943
- FROM $wpdb->posts
944
- WHERE post_name = %s
945
- AND (post_type = 'page' OR post_type = 'attachment')
946
- AND (SELECT qts_id
947
- FROM {$wpdb->prefix}qtranslate_slug
948
- WHERE %d = qts_type
949
- AND ID = qts_id
950
- AND %s = qts_lang
951
- LIMIT 1) IS NULL)",
952
- $leaf_path, QTS_PAGE, $lang, $leaf_path, QTS_PAGE, $lang ); */
953
-
954
- $query = $wpdb->prepare(
955
- " (SELECT ID, qts_slug AS post_name, post_parent
956
- FROM {$wpdb->posts}, {$wpdb->prefix}qtranslate_slug
957
- WHERE %s = qts_slug
958
- AND %d = qts_type
959
- AND %s = qts_lang
960
- AND qts_id = ID)
961
- UNION (SELECT ID, post_name, post_parent
962
- FROM $wpdb->posts
963
- WHERE post_name = %s AND (post_type = '$post_type' OR post_type = 'attachment'))",
964
- $leaf_path, QTS_PAGE, $lang, $leaf_path );
965
- $pages = $wpdb->get_results($query);
966
-
967
- //$fb && fb($query, 'pages query') && fb($pages, '$pages');
968
-
969
- foreach ($pages as $page) {
970
- $path = '/' . $leaf_path;
971
- $level = count($spage_paths);
972
- $curpage = $page;
973
- while ($curpage->post_parent != 0) {
974
- $level--;
975
- if ($level < 0) continue 2;
976
- $curpage = $wpdb->get_row( $wpdb->prepare(
977
- "SELECT ID, post_name, post_parent, qts_slug
978
- FROM $wpdb->posts p
979
- LEFT JOIN ( SELECT *
980
- FROM {$wpdb->prefix}qtranslate_slug
981
- WHERE %d = qts_type
982
- AND %d = qts_id
983
- AND %s = qts_lang
984
- ) qts on p.ID = qts.qts_id
985
- WHERE ID = %d
986
- and post_type='$post_type'",
987
- QTS_PAGE, $curpage->post_parent, $lang, $curpage->post_parent ));
988
- /* This makes invalid the default slug, if it was defined a slug in the desired language.
989
- * However, without other modifications, the default slug is found anyway by wordpress, so we can find it here.
990
- if ($curpage->qts_slug){
991
- if ($curpage->qts_slug === $spage_paths[$level]){
992
- $path = '/' . $curpage->qts_slug . $path;
993
- } else {
994
- continue 2;
995
- }
996
- }*/
997
-
998
-
999
- if ( isset($curpage) && $curpage->qts_slug === $spage_paths[$level]){
1000
- $path = '/' . $curpage->qts_slug . $path;
1001
- } else if (isset($curpage) && $curpage->post_name === $spage_paths[$level]) {
1002
- $path = '/' . $curpage->post_name . $path;
1003
- } else {
1004
- continue 2;
1005
- }
1006
  }
1007
 
1008
- if ( $path === $full_path ) {
1009
- //$fb && fb($level, 'final $level') && fb ($page->ID, '$page->ID');
1010
- return $page->ID;
1011
  }
 
 
 
 
 
 
 
1012
  }
 
1013
 
1014
- return null;
1015
- }
 
 
 
 
 
 
 
 
 
 
 
 
1016
 
1017
- /**
1018
- * Actions used to insert and edit the slug translations
1019
- */
1020
- // post / pages
1021
- add_action('admin_menu', 'qTranslateSlug_add_custom_box');
1022
- add_action('save_post', 'qTranslateSlug_save_postdata', 605, 2);
1023
-
1024
- // Categories / Tags /Taxonomies
1025
- add_action ('edit_category_form_fields', 'qTranslateSlug_tag_fields');
1026
- add_action ('edit_tag_form_fields', 'qTranslateSlug_tag_fields');
1027
- add_action ('edited_term', 'save_qTranslateSlug_term_fields', 605, 3);
1028
-
1029
- function qTranslateSlug_add_custom_box() {
1030
- if ( function_exists( 'add_meta_box' ) ) {
1031
- add_meta_box( 'qts_sectionid', 'Slug', 'qTranslateSlug_custom_box', 'post', 'side', 'high');
1032
- add_meta_box( 'qts_sectionid', 'Slug', 'qTranslateSlug_custom_box', 'page', 'side', 'high' );
1033
- foreach ( get_post_types( array('_builtin' => false ) ) as $ptype ) {
1034
- add_meta_box( 'qts_sectionid', 'Slug', 'qTranslateSlug_custom_box', $ptype, 'side', 'high' );
1035
- }
1036
- }
1037
- }
1038
 
1039
- /**
1040
- * Shows the fields where insert the translated slugs in the post and page edit form.
1041
- */
1042
- function qTranslateSlug_custom_box() {
1043
- global $post, $wpdb, $q_config;
1044
-
1045
- $post_types = get_post_types(array('_builtin' => false ));
1046
-
1047
- if ( 'page' == $post->post_type || in_array($post->post_type, $post_types) ) {
1048
- $post_type = QTS_PAGE;
1049
- } else if ($post->post_type == 'post') {
1050
- $post_type = QTS_POST;
1051
- } else {
1052
- return;
1053
- }
1054
-
1055
- $query = $wpdb->prepare(
1056
- "SELECT qts_lang, qts_slug
1057
- FROM {$wpdb->prefix}qtranslate_slug
1058
- WHERE %d = qts_type
1059
- AND %d = qts_id"
1060
- , $post_type, $post->ID);
1061
- $results = $wpdb->get_results($query);
1062
- $slugs = array();
1063
- foreach ($results as $res) {
1064
- $slugs[$res->qts_lang] = $res->qts_slug;
1065
- }
1066
-
1067
- // Use nonce for verification
1068
- echo '<table style="width:100%">';
1069
- echo '<input type="hidden" name="qts_nonce" id="qts_nonce" value="' . wp_create_nonce( 'qts_nonce' ) . '" />';
1070
-
1071
- foreach($q_config['enabled_languages'] as $lang) {
1072
- echo '<tr>';
1073
- echo "<th style=\"text-align:left; width:10%; color:#555\"><label for='qts_{$lang}_slug'>".__($q_config['language_name'][$lang], 'qtranslate')."</label></th>";
1074
- $value = isset($slugs[$lang])?htmlspecialchars($slugs[$lang],ENT_QUOTES):'';
1075
- echo "<td><input type='text' id='qts_{$lang}_slug' name='qts_{$lang}_slug' value='$value' style='width:90%; margin-left:10%; color:#777' /></td>\n";
1076
- echo '</tr>';
1077
- }
1078
- echo '</table>';
1079
- }
1080
 
 
1081
 
1082
- function qTranslateSlug_get_term_type($str) {
1083
- $tag_type = QTS_TAX;
1084
- if ($str == 'category') {
1085
- $tag_type = QTS_CAT;
1086
- } elseif ($str == 'post_tag') {
1087
- $tag_type = QTS_TAG;
1088
- }
1089
- return $tag_type;
1090
- }
 
 
 
 
 
1091
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1092
 
1093
- function qTranslateSlug_tag_fields( $tag ) { //check for existing featured ID
1094
- $t_id = $tag->term_id;
1095
- //$cat_meta = get_option( "category_$t_id");
1096
-
1097
- if ($_GET['taxonomy'] == 'newspaper') return $t_id;
1098
-
1099
- $tag_type = qTranslateSlug_get_term_type($tag->taxonomy);
1100
-
1101
- global $post, $wpdb, $q_config;
1102
- $query = $wpdb->prepare(
1103
- "SELECT qts_lang, qts_slug
1104
- FROM {$wpdb->prefix}qtranslate_slug
1105
- WHERE %d = qts_type
1106
- AND %d = qts_id"
1107
- , $tag_type, $t_id);
1108
- $results = $wpdb->get_results($query);
1109
- $slugs = array();
1110
- foreach ($results as $res) {
1111
- $slugs[$res->qts_lang] = $res->qts_slug;
1112
- }
1113
-
1114
- echo '<table class="form-table">';
1115
- echo '<input type="hidden" name="qts_nonce" id="qts_nonce" value="' . wp_create_nonce( 'qts_nonce' ) . '" />';
1116
-
1117
- foreach($q_config['enabled_languages'] as $lang) {
1118
- echo "<tr class='form-field form-required'><th scope='row' valig='top'><label for='qts_{$lang}_slug'>Slug (".__($q_config['language_name'][$lang], 'qtranslate').")</label></th>";
1119
- $value = isset($slugs[$lang])?htmlspecialchars($slugs[$lang],ENT_QUOTES):'';
1120
- echo "<td><input type='text' name='qts_{$lang}_slug' value='$value' /></td></tr>\n";
1121
- }
1122
- echo '</table>';
1123
- }
1124
 
 
 
 
 
 
 
 
 
1125
 
1126
- function save_qTranslateSlug_term_fields( $term_id, $tt_id, $taxonomy ) {
1127
- global $wpdb, $q_config, $post_type_object;
1128
-
1129
-
1130
- if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
1131
- || (!isset($_POST['tag_ID']) || $term_id != $_POST['tag_ID'])
1132
- || (!current_user_can('edit_posts'))) {
1133
- return $term_id;
1134
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1135
 
1136
- if ( !wp_verify_nonce( $_POST['qts_nonce'], 'qts_nonce' )) {
1137
- return;
1138
- }
1139
-
1140
- $tag_type = qTranslateSlug_get_term_type($taxonomy);
1141
-
1142
-
1143
- foreach($q_config['enabled_languages'] as $lang) {
1144
- if (isset($_POST["qts_{$lang}_slug"])){
1145
- $slug = sanitize_title($_POST["qts_{$lang}_slug"]);
1146
- if ($slug === ''){
1147
- $remove[] = $wpdb->prepare('%s',$lang);
1148
- } else {
1149
- $update[] = $wpdb->prepare("(%d,%d,%s,%s)",$tag_type,$term_id,$lang,$slug);
1150
- }
1151
- }
1152
- }
1153
-
1154
- if (isset($remove)){
1155
- $sql = $wpdb->prepare("DELETE FROM {$wpdb->prefix}qtranslate_slug
1156
- WHERE qts_type = %d
1157
- AND qts_id = %d
1158
- AND qts_lang in (",
1159
- $tag_type, $term_id) . implode(',',$remove) . ')';
1160
- $res = $wpdb->query($sql);
1161
- //$fb && fb($sql, 'remove query') && fb($res, 'remove results');
1162
- }
1163
- if (isset($update)){
1164
- $sql = "INSERT INTO {$wpdb->prefix}qtranslate_slug (qts_type,qts_id,qts_lang,qts_slug) VALUES "
1165
- . implode(',',$update)
1166
- . " ON DUPLICATE KEY UPDATE qts_slug=VALUES(qts_slug)";
1167
- $res = $wpdb->query($sql);
1168
- //$fb && fb($sql, 'update query') && fb($res, 'update results');
1169
- }
1170
- }
1171
 
 
 
 
 
 
 
 
1172
 
 
 
1173
 
1174
- /**
1175
- * Saves the translated slug when the page is saved
1176
- *
1177
- * @param $post_id the post id
1178
- * @param $post the post object
1179
- */
1180
- function qTranslateSlug_save_postdata( $post_id, $post ) {
1181
- static $last_done = '';
1182
-
1183
- global $wpdb, $q_config;
1184
- //$fb = function_exists('fb');
1185
- //$fb && fb($_POST,'$_POST') && fb($last_done,'$last_done');
1186
 
1187
- // verify this came from the our screen and with proper authorization,
1188
- // because save_post can be triggered at other times
1189
 
1190
- if (!isset($_POST['qts_nonce'])) return;
1191
-
1192
- if (!wp_verify_nonce( $_POST['qts_nonce'], 'qts_nonce' )) return;
1193
-
1194
- $post_types = get_post_types(array('_builtin' => false ));
1195
-
1196
- if ( 'page' == $post->post_type || in_array($post->post_type, $post_types) ) {
1197
- $type = QTS_PAGE;
1198
- if ( !current_user_can( 'edit_page', $post_id ))
1199
- return;
1200
- } else if ( 'post' == $post->post_type ) {
1201
- $type = QTS_POST;
1202
- if ( !current_user_can( 'edit_post', $post_id ))
1203
- return;
1204
- } else {
1205
- return;
1206
- }
1207
-
1208
- // OK, we're authenticated: we need to find and save the data
1209
- if ($last_done === $post_id) {
1210
- return;
1211
- } else {
1212
- $last_done = $post_id;
1213
- }
1214
-
1215
- $update = array();
1216
- $remove = array();
1217
-
1218
- ### DO AUTO-TITLE SLUG HERE!!!! $_POST['post_name']
1219
-
1220
- foreach($q_config['enabled_languages'] as $lang) {
1221
- if (isset($_POST["qts_{$lang}_slug"])){
1222
- $slug = sanitize_title($_POST["qts_{$lang}_slug"]);
1223
- if ($slug === ''){
1224
- $remove[] = $wpdb->prepare('%s',$lang);
1225
- } else {
1226
- $update[] = $wpdb->prepare("(%d,%d,%s,%s)",$type,$post_id,$lang,$slug);
1227
- }
1228
- }
1229
- }
1230
-
1231
- if ($remove){
1232
- $sql = $wpdb->prepare("DELETE FROM {$wpdb->prefix}qtranslate_slug
1233
- WHERE qts_type = %d
1234
- AND qts_id = %d
1235
- AND qts_lang in (",
1236
- $type, $post_id) . implode(',',$remove) . ')';
1237
- $res = $wpdb->query($sql);
1238
- //$fb && fb($sql, 'remove query') && fb($res, 'remove results');
1239
- }
1240
- if ($update){
1241
- $sql = "INSERT INTO {$wpdb->prefix}qtranslate_slug (qts_type,qts_id,qts_lang,qts_slug) VALUES "
1242
- . implode(',',$update)
1243
- . " ON DUPLICATE KEY UPDATE qts_slug=VALUES(qts_slug)";
1244
- $res = $wpdb->query($sql);
1245
- //$fb && fb($sql, 'update query') && fb($res, 'update results');
1246
- }
1247
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1248
 
1249
- // Language Select Code for non-Widget users
1250
- function qTranslateSlug_generateLanguageSelectCode($style='', $id='qtrans_language_chooser') {
1251
-
1252
- global $q_config;
1253
-
1254
- if($style=='') $style='text';
1255
- if(is_bool($style)&&$style) $style='image';
1256
- switch($style) {
1257
- case 'image':
1258
- case 'text':
1259
- case 'dropdown':
1260
- echo '<ul class="qtrans_language_chooser" id="'.$id.'">';
1261
- $sorted_languages = qtrans_getSortedLanguages();
1262
- $counter_ = 0;
1263
- $counter_total_ = count($sorted_languages);
1264
- foreach($sorted_languages as $language) {
1265
- $counter_ ++;
1266
- $last_class = ' ';
1267
- if($counter_ == $counter_total_) $last_class = ' last-child';
1268
- echo '<li';
1269
- if((string)$language == (string)$q_config['language']):
1270
- echo ' class="active'.$last_class.'"';
1271
- else:
1272
- echo ' class="'.$last_class.'"';
1273
- endif;
1274
- echo '><a href="'.qTranslateSlug_getSelfUrl($language).'"';
1275
- // set hreflang
1276
- echo ' hreflang="'.$language.'"';
1277
- if($style=='image')
1278
- echo ' class="qtrans_flag qtrans_flag_'.$language.'"';
1279
- echo '><span';
1280
- if($style=='image')
1281
- echo ' style="display:none"';
1282
- echo '>'.$language.'</span></a></li>';
1283
  }
1284
- echo "</ul><div class=\"qtrans_widget_end\"></div>";
1285
- if($style=='dropdown') {
1286
- echo "<script type=\"text/javascript\">\n// <![CDATA[\r\n";
1287
- echo "var lc = document.getElementById('".$id."');\n";
1288
- echo "var s = document.createElement('select');\n";
1289
- echo "s.id = 'qtrans_select_".$id."';\n";
1290
- echo "lc.parentNode.insertBefore(s,lc);";
1291
- // create dropdown fields for each language
1292
- foreach(qtrans_getSortedLanguages() as $language) {
1293
- echo qtrans_insertDropDownElement($language, qTranslateSlug_getSelfUrl($language), $id);
1294
- }
1295
- // hide html language chooser text
1296
- echo "s.onchange = function() { document.location.href = this.value;}\n";
1297
- echo "lc.style.display='none';\n";
1298
- echo "// ]]>\n</script>\n";
 
 
 
1299
  }
1300
- break;
1301
- case 'both':
1302
- echo '<ul class="qtrans_language_chooser" id="'.$id.'">';
1303
- $sorted_languages = qtrans_getSortedLanguages();
1304
- $counter_ = 0;
1305
- $counter_total_ = count($sorted_languages);
1306
- foreach($sorted_languages as $language) {
1307
- $counter_ ++;
1308
- $last_class = ' ';
1309
- if($counter_ == $counter_total_) $last_class = ' last-child';
1310
- echo '<li';
1311
- if($language == $q_config['language']):
1312
- echo ' class="active'.$last_class.'"';
1313
- else:
1314
- echo ' class="'.$last_class.'"';
1315
- endif;
1316
- echo '><a href="'.qTranslateSlug_getSelfUrl($language).'"';
1317
- echo ' class="qtrans_flag_'.$language.' qtrans_flag_and_text"';
1318
- echo '><span>'.$q_config['language_name'][$language].'</span></a></li>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1319
  }
1320
- echo "</ul><div class=\"qtrans_widget_end\"></div>";
1321
- break;
1322
  }
1323
- }
1324
-
1325
- class qTranslateslugWidget extends WP_Widget {
1326
- function qTranslateslugWidget() {
1327
- $widget_ops = array('classname' => 'widget_qtranslateslug', 'description' => __('Allows your visitors to choose a Language.','qtranslate') );
1328
- $this->WP_Widget('qtranslateslug', 'qTranslate slug widget', $widget_ops);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1329
  }
1330
 
1331
- function widget($args, $instance) {
1332
- extract($args);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1333
 
1334
- echo $before_widget;
1335
- $title = empty($instance['title']) ? __('Language', 'qtranslate') : apply_filters('widget_title', $instance['title']);
1336
- $hide_title = empty($instance['hide-title']) ? false : 'on';
1337
- $type = $instance['type'];
1338
- if($type!='text'&&$type!='image'&&$type!='both'&&$type!='dropdown') $type='text';
1339
-
1340
- if($hide_title!='on') { echo $before_title . $title . $after_title; };
1341
- qTranslateSlug_generateLanguageSelectCode($type, $this->id);
1342
- echo $after_widget;
1343
  }
1344
 
1345
- function update($new_instance, $old_instance) {
1346
- $instance = $old_instance;
1347
- $instance['title'] = $new_instance['title'];
1348
- $instance['hide-title'] = $new_instance['hide-title'];
1349
- $instance['type'] = $new_instance['type'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1350
 
1351
- return $instance;
1352
  }
1353
 
1354
- function form($instance) {
1355
- $instance = wp_parse_args( (array) $instance, array( 'title' => '', 'hide-title' => false, 'type' => 'text' ) );
1356
- $title = $instance['title'];
1357
- $hide_title = $instance['hide-title'];
1358
- $type = $instance['type'];
1359
- ?>
1360
- <p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'qtranslate'); ?> <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo attribute_escape($title); ?>" /></label></p>
1361
- <p><label for="<?php echo $this->get_field_id('hide-title'); ?>"><?php _e('Hide Title:', 'qtranslate'); ?> <input type="checkbox" id="<?php echo $this->get_field_id('hide-title'); ?>" name="<?php echo $this->get_field_name('hide-title'); ?>" <?php echo ($hide_title=='on')?'checked="checked"':''; ?>/></label></p>
1362
- <p><?php _e('Display:', 'qtranslate'); ?></p>
1363
- <p><label for="<?php echo $this->get_field_id('type'); ?>1"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>1" value="text"<?php echo ($type=='text')?' checked="checked"':'' ?>/> <?php _e('Text only', 'qtranslate'); ?></label></p>
1364
- <p><label for="<?php echo $this->get_field_id('type'); ?>2"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>2" value="image"<?php echo ($type=='image')?' checked="checked"':'' ?>/> <?php _e('Image only', 'qtranslate'); ?></label></p>
1365
- <p><label for="<?php echo $this->get_field_id('type'); ?>3"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>3" value="both"<?php echo ($type=='both')?' checked="checked"':'' ?>/> <?php _e('Text and Image', 'qtranslate'); ?></label></p>
1366
- <p><label for="<?php echo $this->get_field_id('type'); ?>4"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>4" value="dropdown"<?php echo ($type=='dropdown')?' checked="checked"':'' ?>/> <?php _e('Dropdown Box', 'qtranslate'); ?></label></p>
1367
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1368
  }
1369
- }
1370
-
1371
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1372
 
1373
- /**
1374
- * adds support for qtranslate nav menus
1375
- * @package Qtranslate Slug
1376
- * @version 0.9
1377
- **/
1378
- function wa_admin_init() {
1379
- global $pagenow;
1380
- if( $pagenow != 'nav-menus.php' ) return;
1381
-
1382
- wp_enqueue_script('nav-menu-query', plugins_url( 'js/qt-nav-menu-min.js' , __FILE__ ) , 'nav-menu', '1.0');
1383
- add_meta_box( 'qt-languages', __('Languages'), 'qt_languages_meta_box', 'nav-menus', 'side', 'default' );
1384
- }
1385
 
1386
- function qt_languages_meta_box() {
1387
- global $q_config;
1388
- echo '<p>';
1389
- foreach($q_config['enabled_languages'] as $id => $language) {
1390
- $checked = ($language == $q_config['language']) ? ' checked="checked"' : '';
1391
- echo '<p style="margin:0 0 5px 0"><input type="radio" style="margin-right:5px" name="wa_qt_lang" value="' . $language . '" id="wa_gt_lang_' . $id . '" ' . $checked . '/>';
1392
- echo '<label for="wa_gt_lang_' . $id . '">';
1393
- echo '<img src="' . trailingslashit(WP_CONTENT_URL).$q_config['flag_location'].$q_config['flag'][$language] . '"/>&nbsp;';
1394
- echo __($q_config['language_name'][$language], 'qtranslate');
1395
- echo '</label></p>';
1396
  }
1397
- echo '</p>';
1398
- }
1399
- add_action('admin_init', 'wa_admin_init');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1401
 
1402
- /**
1403
- * adds support for qtranslate in taxonomies
1404
- * @package Qtranslate Slug
1405
- * @version 0.8
1406
- **/
1407
- function qtranslate_edit_taxonomies(){
1408
 
1409
- $has_titlte = array('category', 'post_tag');
1410
- //$has_slug = array( 'families' );
1411
 
1412
- $args = array( 'public' => true, 'show_ui' => true, '_builtin' => true );
1413
- $categories = get_taxonomies($args, 'object');
1414
- $args = array( 'public' => true, '_builtin' => false );
1415
- $taxonomies = get_taxonomies($args, 'object' );
1416
 
1417
- $taxonomies = array_merge( $categories, $taxonomies );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1418
 
1419
- if ($taxonomies) {
1420
- foreach ($taxonomies as $taxonomy ) {
1421
- if (in_array($taxonomy->name, $has_titlte) ) {
1422
  add_action( $taxonomy->name.'_add_form', 'qtrans_modifyTermFormFor');
1423
  add_action( $taxonomy->name.'_edit_form', 'qtrans_modifyTermFormFor');
 
 
 
 
1424
  }
1425
  }
1426
  }
1427
-
1428
- }
1429
- add_action('admin_menu', 'qtranslate_edit_taxonomies', 805);
1430
- add_filter('single_term_title', 'qtrans_useTermLib', 805);
1431
-
1432
-
1433
-
1434
- /**
1435
- * adds support for qtranslateSlug in taxonomies
1436
- * @package Qtranslate Slug
1437
- * @version 0.8
1438
- **/
1439
- /*
1440
- function qtranslateSlug_filter_taxonomies(){
1441
 
1442
- if ( !isset($_GET['action']) || $_GET['action'] != 'edit' || !isset($_GET['taxonomy']) || !isset($_GET['tag_ID']) ) return false;
1443
 
1444
- $has_slug = array( 'category', 'post_tag');
1445
 
1446
- if (!in_array($_GET['taxonomy'], $has_slug) ) {
1447
- remove_action('edit_category_form_fields', 'qTranslateSlug_tag_fields');
1448
- remove_action('edit_tag_form_fields', 'qTranslateSlug_tag_fields');
1449
- remove_action('edited_term', 'save_qTranslateSlug_term_fields', 10, 3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1450
  }
1451
  }
1452
- add_action('admin_init', 'qtranslateSlug_filter_taxonomies', 800);
1453
- */
 
1454
 
1455
  /**
1456
- * hide quickedit button (functionality not supported by qTranslate)
1457
- * @package Qtranslate Slug
1458
- * @version 0.8
1459
- **/
1460
- function hide_quick_edit_script() {
1461
- global $pagenow;
1462
-
1463
- if (is_admin())
1464
- echo"
1465
- <script type=\"text/javascript\">
1466
- jQuery(document).ready(function($) {
1467
- // Removing Quick Edit button
1468
- var editinline = $('a.editinline');
1469
- if(editinline.length > 0) editinline.parent().remove();
1470
- });
1471
- </script>";
1472
- }
1473
- add_action('admin_footer','hide_quick_edit_script', 600);
1474
 
1475
 
1476
 
1477
  /**
1478
- * get traduction slug for post type
1479
- * @package Qtranslate Slug
1480
- * @version 0.8
1481
- **/
1482
- function get_custom_post_type_slug($post_type) {
1483
- global $custom_post_types_slugs, $q_config, $qts_use_language;
1484
-
1485
- if(!function_exists('qTranslateSlug_post_type_link') || !isset($custom_post_types_slugs) ) return $post_type;
1486
-
1487
- $lang = ($qts_use_language === null) ? $q_config['language'] : $qts_use_language;
1488
-
1489
- if (is_array($custom_post_types_slugs[$post_type])) {
1490
- return $custom_post_types_slugs[$post_type][$lang];
1491
- } else {
1492
- return $post_type;
1493
- }
1494
- }
1495
 
1496
- function get_custom_taxonomy_slug($taxonomy) {
1497
- global $taxonomies_slugs, $q_config, $qts_use_language;
1498
-
1499
- if(!function_exists('qTranslateSlug_term_link') || !isset($taxonomies_slugs) ) return $taxonomy;
1500
 
1501
- $lang = ($qts_use_language === null) ? $q_config['language'] : $qts_use_language;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1502
 
1503
- if (is_array($taxonomies_slugs[$taxonomy])) {
1504
- return $taxonomies_slugs[$taxonomy][$lang];
1505
- } else {
1506
- return $taxonomy;
1507
- }
1508
  }
1509
 
1510
 
1511
- function qtranslateSlug_blog_names($blogs) {
 
 
 
 
 
 
 
 
 
 
1512
 
1513
- foreach ($blogs as $blog) {
1514
- $blog->blogname = __($blog->blogname);
 
 
 
 
1515
  }
1516
- return $blogs;
1517
  }
 
1518
 
1519
- add_filter( 'get_blogs_of_user', 'qtranslateSlug_blog_names', 1 );
1520
 
1521
 
1522
- function qtranslug_widget_init() {
1523
- register_widget('qTranslateslugWidget');
1524
- }
1525
- add_action('widgets_init', 'qtranslug_widget_init');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
  /*
3
  Plugin Name: qTranslate slug
4
+ Plugin URI: http://not-only-code.github.com/qtranslate-slug/
5
  Description: Allows to define a slug for each language and some qTranslate bug fixes
6
+ Version: 1.0
7
  Author: Carlos Sanz Garcia
8
+ Author URI: http://github.com/not-only-code
9
 
10
+
11
+ This plugin (version 1.0) has been written from scratch using OOP. The code has been structured better, the functions have been marked and commented and everything is better integrated with Wordpress API. Previous versions of this plugin was based on Qtranslate Slug with Widget plugin (http://wordpress.org/extend/plugins/qtranslate-slug-with-widget/).
12
 
13
  --------------------------------------------------------------------------------------------------------
14
 
15
+ version 1.0
16
+ * new branch, the plugin has been rewrited: now the code is commented and wrapped inside a class, much code has change and the performance has been increased. √
17
+ * structural changes:
18
+ * no ID for slug type, then don't install qtrasnlate_slug table. √
19
+ * slugs now are stored on meta tables, installation creates a termmeta table with some new 'core functions' to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/) √
20
+ * some automation:
21
+ * the plugin generates translated slug automatically from title in empty cases (like wordpress) √
22
+ * the plugin checks if the slug already exists (per each language and type / taxonomy), and adds a progressive number in this case (like wordpress) √
23
+ * works on ajax requests like creatig new taxonomies on edit post page √
24
+ * possibility to translate the base of permastructs for 'post_types' and 'taxonomies' (uses $wp_rewrite) √
25
+ * added some filters:
26
+ * 'qts_validate_post_slug' : args( $post (object), $slug (string), $lang (string) ) / filter to process the post slug before is saved on the database.
27
+ * 'qts_validate_term_slug' : args( $term (object), $slug (string), $lang (string) ) / filter to process the term slug before is saved on the database.
28
+ * 'qts_current_url' : args ( $url (string), $lang (string) ) / filter to process the entire url after it has been generated.
29
+ * 'qts_permastruct' : args ( $permastruct (string), $name (string) ) / filter to process the permastruct, used for change the base.
30
+ * added plugin language textdomain (.pot file) √
31
+ * new admin options page for save the base permastructs √
32
+ * import process when the plugin updates older versions
33
+ * updated Language selector Widget
34
+ * some bug fixes √
35
+ * some Qtranslate patches
36
 
37
  version 0.9
38
+ * some wordpress qTranslate bug fixes
39
+ * adds a javascript solution for qTranslate Nav Menus
40
 
41
  version 0.8
42
+ * added support for Categories
43
+ * added support for Tags
44
+ * added support for Taxonomies
45
+ * added support for Custom Post Types
46
 
47
+ version 0.7 enhanced by [Zapo](http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499)
48
+ * added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit
49
 
50
  Version 0.5 and 0.6 enhanched by Marco Del Percio
51
 
52
  --------------------------------------------------------------------------------------------------------
53
 
54
+ TODO:
55
+
56
+ * add support to translate attachment slugs
57
+ * expand qtranslate for translate attachment names and descriptions ( useful for galleries )
58
+ * qtranslate integration with other plugins like Jigoshop, e-commerce, etc.
59
+
60
+ --------------------------------------------------------------------------------------------------------
61
+
62
  This program is free software; you can redistribute it and/or
63
  modify it under the terms of the GNU General Public License
64
  as published by the Free Software Foundation; either version 2
75
 
76
 
77
  The full copy of the GNU General Public License is available here: http://www.gnu.org/licenses/gpl.txt
 
78
  */
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
+ ////////////////////////////////////////////////////////////////////////////////////////
82
 
 
 
 
 
83
 
84
+ if ( !function_exists('_debug') ):
85
+ function _debug( $message ) {
86
+
87
+ if ( WP_DEBUG === true ):
88
+
89
+ if ( is_array( $message ) || is_object( $message ) ) {
90
+
91
+ error_log( print_r( $message, true ) );
92
+
93
+ } else {
94
+
95
+ error_log( $message );
96
+ }
97
+
98
+ endif;
99
+ }
100
+ endif;
101
+
102
+ ////////////////////////////////////////////////////////////////////////////////////////
103
+
104
 
105
  /**
106
+ * QtranslateSlugWidget class
107
+ *
108
+ * @since 1.0
109
  */
110
+ class QtranslateSlugWidget extends WP_Widget {
111
+
112
+ function QtranslateSlugWidget() {
113
+ $widget_ops = array('classname' => 'qts_widget', 'description' => __('Allows your visitors to choose a Language.','qtranslate') );
114
+ $this->WP_Widget('qtranslateslug', __('Language selector', 'qts'), $widget_ops);
115
+ }
116
+
117
+ function widget($args, $instance) {
118
+ extract($args);
119
+
120
+ echo $before_widget;
121
+ $title = empty($instance['title']) ? __('Language', 'qtranslate') : apply_filters('widget_title', $instance['title']);
122
+ $hide_title = empty($instance['hide-title']) ? false : 'on';
123
+ $type = $instance['type'];
124
+ $short_text = ($instance['short_text'] == 'on') ? true : false ;
125
+
126
+ if( $type!='text' && $type!='image' && $type!='both' && $type!='dropdown' ) $type='text';
127
 
128
+ if( $hide_title!='on')
129
+ echo $before_title . $title . $after_title;
130
 
131
+ qts_language_menu($type, array( 'id' => $this->id, 'short' => $short_text ) );
132
+
133
+ echo $after_widget;
134
+ }
135
+
136
+ function update($new_instance, $old_instance) {
137
+ $instance = $old_instance;
138
+ $instance['title'] = $new_instance['title'];
139
+ $instance['hide-title'] = $new_instance['hide-title'];
140
+ $instance['type'] = $new_instance['type'];
141
+ $instance['short_text'] = $new_instance['short_text'];
142
+
143
+ return $instance;
144
+ }
145
+
146
+ function form($instance) {
147
+ $instance = wp_parse_args( (array) $instance, array( 'title' => '', 'hide-title' => false, 'type' => 'text' ) );
148
+ $title = $instance['title'];
149
+ $hide_title = $instance['hide-title'];
150
+ $type = $instance['type'];
151
+ $short_text = $instance['short_text'];
152
+ ?>
153
+ <p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'qtranslate'); ?> <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($title); ?>" /></label></p>
154
+ <p><label for="<?php echo $this->get_field_id('hide-title'); ?>"><?php _e('Hide Title:', 'qtranslate'); ?> <input type="checkbox" id="<?php echo $this->get_field_id('hide-title'); ?>" name="<?php echo $this->get_field_name('hide-title'); ?>" <?php echo ($hide_title=='on')?'checked="checked"':''; ?>/></label></p>
155
+ <p><?php _e('Display:', 'qtranslate'); ?></p>
156
+ <p><label for="<?php echo $this->get_field_id('type'); ?>1"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>1" value="text"<?php echo ($type=='text')?' checked="checked"':'' ?>/> <?php _e('Text only', 'qtranslate'); ?></label></p>
157
+ <p><label for="<?php echo $this->get_field_id('type'); ?>2"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>2" value="image"<?php echo ($type=='image')?' checked="checked"':'' ?>/> <?php _e('Image only', 'qtranslate'); ?></label></p>
158
+ <p><label for="<?php echo $this->get_field_id('type'); ?>3"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>3" value="both"<?php echo ($type=='both')?' checked="checked"':'' ?>/> <?php _e('Text and Image', 'qtranslate'); ?></label></p>
159
+ <p><label for="<?php echo $this->get_field_id('type'); ?>4"><input type="radio" name="<?php echo $this->get_field_name('type'); ?>" id="<?php echo $this->get_field_id('type'); ?>4" value="dropdown"<?php echo ($type=='dropdown')?' checked="checked"':'' ?>/> <?php _e('Dropdown Box', 'qtranslate'); ?></label></p>
160
+ <p><label for="<?php echo $this->get_field_id('short_text'); ?>"><?php _e('Show short name (en):', 'qts'); ?> <input type="checkbox" id="<?php echo $this->get_field_id('short_text'); ?>" name="<?php echo $this->get_field_name('short_text'); ?>" <?php checked($short_text, 'on') ?>/></label></p>
161
+ <p><?php _e('Display:', 'qtranslate'); ?></p>
162
+
163
+ <?php
164
+ }
165
  }
166
+ ////////////////////////////////////////////////////////////////////////////////////////
 
167
 
168
 
169
 
170
+ /**
171
+ * QtranslateSlug class
172
+ *
173
+ * @since 1.0
174
+ */
175
+ class QtranslateSlug {
176
+
177
+
178
+ /**
179
+ * array with old data system
180
+ *
181
+ * @var bool
182
+ *
183
+ * @since 1.0
184
+ */
185
+ private $old_data = null;
186
 
 
187
 
 
188
 
189
+ /**
190
+ * stores permalink_structure option, for save queries to db
191
+ *
192
+ * @var string
193
+ *
194
+ * @since 1.0
195
+ */
196
+ private $permalink_structure;
197
+
198
+
199
+
200
+ /**
201
+ * Stores options slugs from database
202
+ *
203
+ * @var array
204
+ *
205
+ * @since 1.0
206
+ */
207
+ protected $options;
208
+
209
+
210
+
211
+ /**
212
+ * Variable used to override the language
213
+ *
214
+ * @var string
215
+ *
216
+ * @since 1.0
217
+ */
218
+ private $lang = false;
219
+
220
+
221
+
222
+ /**
223
+ * slug in meta_key name in meta tables
224
+ *
225
+ * @var string
226
+ *
227
+ * @since 1.0
228
+ */
229
+ private $meta_key = "_qts_slug_%s";
230
+
231
+
232
+
233
+ /**
234
+ * Array of translated versions of the current url
235
+ *
236
+ * @var array
237
+ *
238
+ * @since 1.0
239
+ */
240
+ private $current_url = array();
241
+
242
+
243
+
244
+ /**
245
+ * return the current / temp language
246
+ *
247
+ * @since 1.0
248
+ */
249
+ private function get_lang() {
250
+ global $q_config;
251
+
252
+ return ($this->lang) ? $this->lang : $q_config['language'];
253
  }
254
+
255
+
256
+
257
+ /**
258
+ * getter: options
259
+ *
260
+ * @since 1.0
261
+ */
262
+ public function get_options() {
263
+ $this->set_options();
264
+ return $this->options;
 
 
 
 
 
 
 
 
 
265
  }
266
+
267
+
268
+
269
+ /**
270
+ * setter: options | permalink_structure
271
+ *
272
+ * @since 1.0
273
+ */
274
+ public function set_options() {
275
+ if (empty($this->options))
276
+ $this->options = get_option(QTS_OPTIONS_NAME);
277
+
278
+ if (!$this->options)
279
+ add_option(QTS_OPTIONS_NAME, array());
280
+
281
+ if (is_null($this->permalink_structure))
282
+ $this->permalink_structure = get_option('permalink_structure');
 
 
 
 
283
  }
284
 
285
+
286
+
287
+ /**
288
+ * setter: options | permalink_structure
289
+ *
290
+ * @since 1.0
291
+ */
292
+ public function save_options($new_options = false) {
293
+ if (!$new_options || empty($new_options)) return;
294
+
295
+ if (count($this->options) != count($new_options)) return;
296
+
297
+ _debug('SAVINNGGGG');
298
+ _debug($new_options);
299
+
300
+ update_option(QTS_OPTIONS_NAME, $new_options);
301
+ $this->options = $new_options;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  }
303
+
304
+
305
+
306
+ /**
307
+ * getter: meta key
308
+ *
309
+ * @since 1.0
310
+ */
311
+ public function get_meta_key( $force_lang = false ) {
312
+ global $q_config;
313
+
314
+ $lang = $this->get_lang();
315
+
316
+ if ($force_lang) $lang = $force_lang;
317
+
318
+ return sprintf($this->meta_key, $lang); // returns: _qts_slug_en
319
+ }
320
+
321
+
322
+
323
+ /**
324
+ * check dependences for activation
325
+ *
326
+ * @since 1.0
327
+ */
328
+ static function block_activate() {
329
+ global $wp_version;
330
+
331
+ return ( version_compare($wp_version, "3.3", "<" ) && !function_exists('qtrans_init') );
332
+ }
333
+
334
+
335
+
336
+ /**
337
+ * check if exists qtranslate and do the installation, support multisite
338
+ *
339
+ * @since 1.0
340
+ */
341
+ public function install() {
342
+ global $wpdb;
343
+
344
+ if ( self::block_activate() ) return;
345
+
346
+ if ( function_exists('is_multisite') && is_multisite() ) {
347
 
348
+ if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
 
 
 
 
 
 
 
 
 
 
 
349
 
350
+ $old_blog = $wpdb->blogid;
351
+ $blogids = $wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs"));
352
+ foreach ($blogids as $blog_id) {
353
+ switch_to_blog($blog_id);
354
+ $this->activate();
 
 
 
 
 
355
  }
356
+ switch_to_blog($old_blog);
357
+ return;
358
  }
359
  }
360
+
361
+ $this->activate();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  }
363
 
 
 
 
 
364
 
365
+
366
+ /**
367
+ * activates and do the installation
368
+ *
369
+ * @since 1.0
370
+ */
371
+ private function activate() {
372
+ global $wp_rewrite;
373
 
374
+ $this->set_options();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
376
+ $qts_version = get_option('qts_version');
377
+
378
+ // checks version and do the installation
379
+ if ( !$qts_version || $qts_version != QTS_VERSION ) {
380
 
381
+ // install termmeta table using functions from Simple-Term-Meta ( http://wordpress.org/extend/plugins/simple-term-meta/ )
382
+ install_term_meta_table();
383
 
384
+ // update installed option
385
+ update_option('qts_version', QTS_VERSION);
 
 
 
 
 
386
  }
387
 
388
+ // regenerate rewrite rules in db
389
+ add_action( 'generate_rewrite_rules', array($this, 'modify_rewrite_rules') );
390
+ flush_rewrite_rules();
391
+ }
392
+
393
+
394
+
395
+ /**
396
+ * actions when deactivating the plugin
397
+ *
398
+ * @since 1.0
399
+ */
400
+ public function deactivate() {
401
+ global $wp_rewrite;
402
+
403
+ // regenerate rewrite rules in db
404
+ remove_action( 'generate_rewrite_rules', array($this, 'modify_rewrite_rules') );
405
+ $wp_rewrite->flush_rules();
406
+ }
407
+
408
+
409
+
410
+ /**
411
+ * admin notice: update your old data
412
+ *
413
+ * @since 1.0
414
+ */
415
+ function notice_update(){
416
+ global $current_screen;
417
 
418
+ if ($current_screen->id != 'settings_page_qtranslate-slug-settings'):
419
+
420
+ echo "<div class=\"updated\">" . PHP_EOL;
421
+ echo "<p><strong>Qtranslate Slug:</strong></p>" . PHP_EOL;
422
+ printf("<p>%s <a href=\"%s\" class=\"button\">%s</a></p>", __('Please update your old data to the new system.', 'qts'), add_query_arg(array('page' => 'qtranslate-slug-settings'), 'options-general.php'), __('upgrade now', 'qts')) . PHP_EOL;
423
+ echo "</div>" . PHP_EOL;
424
+
425
+ endif;
 
 
 
426
  }
427
 
428
+
429
+
430
+ /**
431
+ * admin notice: update your old data
432
+ *
433
+ * @since 1.0
434
+ */
435
+ function notice_dependences(){
436
+ global $current_screen;
437
+
438
+ echo "<div class=\"error\">" . PHP_EOL;
439
+ echo "<p><strong>Qtranslate Slug:</strong></p>" . PHP_EOL;
440
+ echo "<p>" . __('This plugin requires at least <strong>Wordpress 3.3</strong> and <strong>Qtranslate(2.5.8 or newer)</strong>', 'qts') . "</p>" . PHP_EOL;
441
+ echo "</div>" . PHP_EOL;
442
+
443
  }
444
 
 
 
445
 
 
 
446
 
447
+ /**
448
+ * checks if old table 'qtranslate_slug' exists and is not empty
449
+ *
450
+ * @return object | false
451
+ *
452
+ * @since 1.0
453
+ */
454
+ public function check_old_data() {
455
+ global $wpdb;
456
+
457
+ if ($this->old_data === false) return false;
458
+
459
+ $table_name = $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}qtranslate_slug'");
460
+
461
+ if (!empty($table_name))
462
+ $this->old_data = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}qtranslate_slug");
463
+
464
+ if ( empty($table_name) || empty($this->old_data) )
465
+ $this->old_data = false;
466
+
467
+ return $this->old_data;
468
+ }
469
+
470
+
471
 
472
+ /**
473
+ * actions when deactivating the plugin
474
+ *
475
+ * @since 1.0
476
+ */
477
+ private function check_old_versions() {
478
+
479
+ if ( $this->check_old_data() )
480
+ add_action('admin_notices', array($this, 'notice_update'));
481
  }
482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
 
484
+
485
+ /**
486
+ * Initialise the Class with all hooks
487
+ *
488
+ * @since 1.0
489
+ */
490
+ function init() {
491
+ global $pagenow;
492
+
493
+ load_plugin_textdomain( 'qts', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
494
+
495
+ // checking plugin activate
496
+ if ( self::block_activate() ) {
497
+ if (is_admin())
498
+ add_action('admin_notices', array($this, 'notice_dependences'));
499
+ return;
500
+ }
501
+
502
+ // caching qts options
503
+ $this->set_options();
504
+
505
+ if ( is_admin() ) {
506
+
507
+ $this->check_old_versions();
508
+
509
+ // add filters
510
+ add_filter( 'term_name', array($this, 'term_name'), 0, 2 );
511
+ add_filter( 'qts_validate_post_slug', array($this, 'validate_post_slug'), 0, 3 );
512
+ add_filter( 'qts_validate_post_slug', array($this, 'unique_post_slug'), 1, 3 );
513
+ add_filter( 'qts_validate_term_slug', array($this, 'validate_term_slug'), 0, 3 );
514
+ add_filter( 'qts_validate_term_slug', array($this, 'unique_term_slug'), 1, 3 );
515
+
516
+ // admin actions
517
+ add_action( 'admin_menu', array($this, 'add_slug_meta_box') );
518
+ add_action( 'save_post', array($this, 'save_postdata'), 605, 2 );
519
+ add_action( 'delete_term', array($this, 'delete_term'), 0, 3);
520
+ add_action( 'created_term', array($this, 'save_term'), 605, 3);
521
+ add_action( 'edited_term', array($this, 'save_term'), 605, 3 );
522
+ add_action( 'admin_head', array($this, 'hide_slug_box'), 900 );
523
+
524
+ add_action( 'init', array($this, 'taxonomies_hooks'), 805 );
525
+
526
+ add_action( 'wp_dashboard_setup', array($this, 'remove_dashboard_widgets') );
527
+ add_action( 'admin_head', array($this, 'hide_quick_edit'), 600 );
528
+ add_action( 'admin_init', array($this, 'fix_nav_menu') );
529
+
530
+ if ( $pagenow == 'options-permalink.php' )
531
+ add_filter( 'query_vars', array($this, 'query_vars'));
532
+
533
+ } else {
534
+
535
+ add_filter( 'request', array($this, 'filter_request') );
536
+ }
537
+
538
+ add_action( 'generate_rewrite_rules', array($this, 'modify_rewrite_rules') );
539
+
540
+ // remove some Qtranslate filters
541
+ remove_filter( 'page_link', 'qtrans_convertURL' );
542
+ remove_filter( 'post_link', 'qtrans_convertURL' );
543
+ remove_filter( 'category_link', 'qtrans_convertURL' );
544
+ remove_filter( 'tag_link', 'qtrans_convertURL' );
545
+
546
+ add_filter( 'qts_permastruct' , array($this, 'get_extra_permastruct'), 0, 2);
547
+ add_filter( 'qts_url_args', array($this, 'parse_url_args'), 0, 1);
548
+ add_filter( 'home_url', array($this, 'home_url'), 10, 4);
549
+ add_filter( 'post_type_link', array($this, 'post_type_link'), 600, 4 );
550
+ add_filter( 'post_link', array($this, 'post_link'), 0, 3 );
551
+ add_filter( '_get_page_link', array($this, '_get_page_link'), 0, 2 );
552
+ add_filter( 'term_link', array($this, 'term_link'), 600, 3 );
553
+
554
+ add_filter( 'single_term_title', 'qtrans_useTermLib', 805 );
555
+ add_filter( 'get_blogs_of_user', array($this, 'blog_names'), 1 );
556
+ add_action( 'widgets_init', array($this, 'widget_init'), 100 );
557
+ }
558
+
559
 
560
 
561
+ /**
562
+ * Adds news rules to translate the URL bases, this function must be called on flush_rewrite or 'flush_rewrite_rules'
563
+ *
564
+ * @param object $wp_rewrite
565
+ *
566
+ * @since 1.0
567
+ */
568
+ public function modify_rewrite_rules() {
569
+ global $wp_rewrite;
570
+
571
+ // post types rules
572
+ $post_types = get_post_types( array('_builtin' => false ), 'objects');
573
+ foreach ( $post_types as $post_type )
574
+ $this->generate_extra_rules( $post_type->name );
575
+
576
+ // taxonomies rules
577
+ $taxonomies = $this->get_public_taxonomies();
578
+ foreach ( $taxonomies as $taxonomy )
579
+ $this->generate_extra_rules( $taxonomy->name );
580
+ }
581
+
582
+
583
+
584
+ /**
585
+ * Helper: news rules to translate the URL bases
586
+ *
587
+ * @param string $name name of extra permastruct
588
+ * @param string $type 'post_type' or 'taxonomy'
589
+ *
590
+ * @since 1.0
591
+ */
592
+ private function generate_extra_rules( $name = false ) {
593
+ global $wp_rewrite, $q_config;
594
+
595
+ foreach ($q_config['enabled_languages'] as $lang):
596
+
597
+ if ( $base = $this->get_base_slug( $name, $lang) ):
598
 
599
+ $struct = $wp_rewrite->extra_permastructs[$name];
600
 
601
+ if ( is_array( $struct ) ) {
602
+ if ( count( $struct ) == 2 )
603
+ $rules = $wp_rewrite->generate_rewrite_rules( "/$base/%$name%", $struct[1] );
604
+ else
605
+ $rules = $wp_rewrite->generate_rewrite_rules( "/$base/%$name%", $struct['ep_mask'], $struct['paged'], $struct['feed'], $struct['forcomments'], $struct['walk_dirs'], $struct['endpoints'] );
 
 
 
 
 
 
 
606
  } else {
607
+ $rules = $wp_rewrite->generate_rewrite_rules( "/$base/%$name%" );
608
  }
609
+
610
+ $wp_rewrite->rules = array_merge($rules, $wp_rewrite->rules);
611
+
612
+ endif;
613
+
614
+ endforeach;
615
  }
616
 
617
+
618
+
619
+ /**
620
+ * Helper that gets a base slug stored in options
621
+ *
622
+ * @param string $name of extra permastruct
623
+ * @return string base slug for 'post_type' and 'language' or false
624
+ *
625
+ * @since 1.0
626
+ */
627
+ public function get_base_slug($name = false, $lang = false) {
628
+
629
+ if ( !$name || !$lang ) return false;
630
+
631
+ if ( taxonomy_exists($name) ) {
632
+ $type = 'taxonomy';
633
+ } else if ( post_type_exists($name) ) {
634
+ $type = 'post_type';
635
  } else {
636
+ return false;
637
  }
638
+
639
+ $qts_options = $this->get_options();
640
+
641
+ $option_name = QTS_PREFIX . $type . '_' . $name;
642
+
643
+ if ( !isset($qts_options[$option_name]) || empty($qts_options[$option_name]) ) return false;
644
+
645
+ $option = $qts_options[$option_name][$lang];
646
+
647
+ if (isset($option)) return $option;
648
+
649
+ return false;
650
  }
651
 
 
 
652
 
 
 
 
 
 
 
 
 
 
653
 
654
+ /**
655
+ * Helper: returns public built-in and not built-in taxonomies
656
+ *
657
+ * @return array of public taxonomies objects
658
+ *
659
+ * @since 1.0
660
+ */
661
+ private function get_public_taxonomies() {
662
+
663
+ $builtin = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => true ), 'object');
664
+ $taxonomies = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => false ), 'object' );
665
+
666
+ return array_merge( $builtin, $taxonomies );
667
  }
668
 
 
 
669
 
670
+
671
+ /**
672
+ * parse and adds $_GET args passed to an url
673
+ *
674
+ * @param string $url parameters
675
+ * @param string $lang processed
676
+ * @return string converted url
677
+ *
678
+ * @since 1.0
679
+ */
680
+ public function parse_url_args( $url ) {
681
+ global $q_config;
682
+
683
+ if (is_admin()) return $url;
684
+
685
+ $url = preg_replace('/&amp;/', '&', $url);
686
+
687
+ // if no permalink structure ads ?lang=en
688
+ $base_query = parse_url($q_config['url_info']['original_url']);
689
+ $base_args = isset($base_query['query']) ? wp_parse_args($base_query['query']) : array();
690
+
691
+ if ( empty($this->permalink_structure) || $q_config['url_mode'] == 1 )
692
+ $base_args['lang'] = $this->get_lang();
693
+
694
+ // rebulid query with all args
695
+ $url = add_query_arg($base_args, $url);
696
+
697
+ return $url;
698
+ }
699
+
700
+
701
+
702
+ /**
703
+ * Fix get_page_by_path when querying vars
704
+ *
705
+ * @param $query_vars objec query vars founded
706
+ * @return object $query_vars processed
707
+ *
708
+ * @since 1.0
709
+ */
710
+ public function query_vars( $query_vars ) {
711
+ global $wp, $wp_rewrite;
712
+
713
+ $wp->$query_vars = array();
714
+ $post_type_query_vars = array();
715
+
716
+ if ( is_array($extra_query_vars) )
717
+ $wp->extra_query_vars = & $extra_query_vars;
718
+ else if (! empty($extra_query_vars))
719
+ parse_str($extra_query_vars, $wp->extra_query_vars);
720
+
721
+ // Process PATH_INFO, REQUEST_URI, and 404 for permalinks.
722
+
723
+ // Fetch the rewrite rules.
724
+ $rewrite = $wp_rewrite->wp_rewrite_rules();
725
+
726
+ if ( ! empty($rewrite) ) {
727
+ // If we match a rewrite rule, this will be cleared.
728
+ $error = '404';
729
+ $wp->did_permalink = true;
730
+
731
+ if ( isset($_SERVER['PATH_INFO']) )
732
+ $pathinfo = $_SERVER['PATH_INFO'];
733
+ else
734
+ $pathinfo = '';
735
+ $pathinfo_array = explode('?', $pathinfo);
736
+ $pathinfo = str_replace("%", "%25", $pathinfo_array[0]);
737
+ $req_uri = $_SERVER['REQUEST_URI'];
738
+ $req_uri_array = explode('?', $req_uri);
739
+ $req_uri = $req_uri_array[0];
740
+ $self = $_SERVER['PHP_SELF'];
741
+ $home_path = parse_url(home_url());
742
+ if ( isset($home_path['path']) )
743
+ $home_path = $home_path['path'];
744
+ else
745
+ $home_path = '';
746
+ $home_path = trim($home_path, '/');
747
+
748
+ // Trim path info from the end and the leading home path from the
749
+ // front. For path info requests, this leaves us with the requesting
750
+ // filename, if any. For 404 requests, this leaves us with the
751
+ // requested permalink.
752
+ $req_uri = str_replace($pathinfo, '', $req_uri);
753
+ $req_uri = trim($req_uri, '/');
754
+ $req_uri = preg_replace("|^$home_path|", '', $req_uri);
755
+ $req_uri = trim($req_uri, '/');
756
+ $pathinfo = trim($pathinfo, '/');
757
+ $pathinfo = preg_replace("|^$home_path|", '', $pathinfo);
758
+ $pathinfo = trim($pathinfo, '/');
759
+ $self = trim($self, '/');
760
+ $self = preg_replace("|^$home_path|", '', $self);
761
+ $self = trim($self, '/');
762
+
763
+ // The requested permalink is in $pathinfo for path info requests and
764
+ // $req_uri for other requests.
765
+ if ( ! empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo) ) {
766
+ $request = $pathinfo;
767
+ } else {
768
+ // If the request uri is the index, blank it out so that we don't try to match it against a rule.
769
+ if ( $req_uri == $wp_rewrite->index )
770
+ $req_uri = '';
771
+ $request = $req_uri;
772
+ }
773
 
774
+ $wp->request = $request;
775
 
776
+ // Look for matches.
777
+ $request_match = $request;
778
+ if ( empty( $request_match ) ) {
779
+ // An empty request could only match against ^$ regex
780
+ if ( isset( $rewrite['$'] ) ) {
781
+ $wp->matched_rule = '$';
782
+ $query = $rewrite['$'];
783
+ $matches = array('');
784
+ }
785
+ } else if ( $req_uri != 'wp-app.php' ) {
786
+ foreach ( (array) $rewrite as $match => $query ) {
787
+ // If the requesting file is the anchor of the match, prepend it to the path info.
788
+ if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request )
789
+ $request_match = $req_uri . '/' . $request;
790
+
791
+ if ( preg_match("#^$match#", $request_match, $matches) ||
792
+ preg_match("#^$match#", urldecode($request_match), $matches) ) {
793
+
794
+ if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) {
795
+ // this is a verbose page match, lets check to be sure about it
796
+ if ( ! $this->get_page_by_path( $matches[ $varmatch[1] ] ) )
797
+ continue;
798
+ }
799
+
800
+ // Got a match.
801
+ $wp->matched_rule = $match;
802
+ break;
803
+ }
804
+ }
805
+ }
806
 
807
+ if ( isset( $wp->matched_rule ) ) {
808
+ // Trim the query of everything up to the '?'.
809
+ $query = preg_replace("!^.+\?!", '', $query);
 
 
 
 
810
 
811
+ // Substitute the substring matches into the query.
812
+ $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));
813
 
814
+ $wp->matched_query = $query;
815
 
816
+ // Parse the query.
817
+ parse_str($query, $perma_query_vars);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
 
819
+ // If we're processing a 404 request, clear the error var
820
+ // since we found something.
821
+ unset( $_GET['error'] );
822
+ unset( $error );
823
+ }
824
 
825
+ // If req_uri is empty or if it is a request for ourself, unset error.
826
+ if ( empty($request) || $req_uri == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) {
827
+ unset( $_GET['error'] );
828
+ unset( $error );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
829
 
830
+ if ( isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false )
831
+ unset( $perma_query_vars );
832
 
833
+ $wp->did_permalink = false;
834
+ }
835
+ }
836
 
837
+ return $wp->public_query_vars;
838
+ }
 
 
 
 
 
 
 
 
 
839
 
840
+
841
+
842
+ /**
843
+ * Function called when query parameters are processed by Wordpress.
844
+ *
845
+ * @param $query query parameters
846
+ * @return array() $query processed
847
+ *
848
+ * @since 1.0
849
+ */
850
+ function filter_request( $query ) {
851
+ global $q_config, $wp_query;
852
+
853
+ // special conditional for /%postname%/ post structure
854
+ $page_foundit = false;
855
+ if ( $this->permalink_structure == '/%postname%/' ):
856
+ // post or page
857
+ if ( isset($query['name']) && !isset($query['post_type']) ) {
858
+ $page = $this->get_page_by_path($query['name']);
859
+ if ( !is_null($page) ) {
860
+ $id = $page->ID;
861
+ $cache_array = array($page);
862
+ update_post_caches($cache_array, 'page'); // caching query :)
863
+ unset($query['name']);
864
+ $query['pagename'] = get_page_uri($page);
865
+ $function = 'get_page_link';
866
+ $page_foundit = true;
867
+ } else {
868
+ $page = $this->get_page_by_path($query['name'], OBJECT, 'post');
869
+ if (!$page) return $query;
870
+ $query['name'] = $page->post_name;
871
+ $id = $page->ID;
872
+ $cache_array = array($page);
873
+ update_post_caches($cache_array); // caching query :)
874
+ $function = 'get_permalink';
875
+ $page_foundit = true;
876
+ }
877
+ }
878
+ endif;
879
+
880
+ // -> page
881
+ if ( ( isset($query['pagename']) || isset($query['page_id']) ) && !$page_foundit ):
882
+
883
+ $page = isset($query['page_id']) ? get_page($query['page_id']) : $this->get_page_by_path($query['pagename']);
884
+ if (!$page) return $query;
885
+ $id = $page->ID;
886
+ $cache_array = array($page);
887
+ update_post_caches($cache_array, 'page');
888
+ $query['pagename'] = get_page_uri($page);
889
+ $function = 'get_page_link';
890
+
891
+ // -> custom post type
892
+ elseif ( isset($query['post_type']) ):
893
+
894
+ $page = $this->get_page_by_path($query['name'], OBJECT, $query['post_type']);
895
+ if (!$page) return $query;
896
+ $id = $page->ID;
897
+ $cache_array = array($page);
898
+ update_post_caches($cache_array, $query['post_type']); // caching query :)
899
+ $query['name'] = $query[$query['post_type']] = get_page_uri($page);
900
+ $function = 'get_post_permalink';
901
+
902
+ // -> post
903
+ elseif ( (isset($query['name']) || isset($query['p']) ) && !$page_foundit ):
904
+
905
+ $post = isset($query['p']) ? get_post($query['p']) : $this->get_page_by_path($query['name'], OBJECT, 'post');
906
+ if (!$post) return $query;
907
+ $query['name'] = $post->post_name;
908
+ $id = $post->ID;
909
+ $cache_array = array($post);
910
+ update_post_caches($cache_array);
911
+ $function = 'get_permalink';
912
+
913
+ // -> category
914
+ elseif ( ( isset($query['category_name']) || isset($query['cat'])) ):
915
+ if ( isset($query['category_name']) )
916
+ $term_slug = $this->get_last_slash( $query['category_name'] );
917
+ $term = isset($query['cat']) ? get_term($query['cat'], 'category') : $this->get_term_by('slug', $term_slug, 'category');
918
+ if (!$term) return $query;
919
+ $cache_array = array($term);
920
+ update_term_cache($cache_array, 'category'); // caching query :)
921
+ $id = $term->term_id;
922
+ $query['category_name'] = $term->slug; // uri
923
+ $function = 'get_category_link';
924
+
925
+ // -> tag
926
+ elseif ( isset($query['tag']) ):
927
+
928
+ $term = $this->get_term_by('slug', $query['tag'], 'post_tag');
929
+ if (!$term) return $query;
930
+ $cache_array = array($term);
931
+ update_term_cache($cache_array, 'post_tag'); // caching query :)
932
+ $id = $term->term_id;
933
+ $query['tag'] = $term->slug;
934
+ $function = 'get_tag_link';
935
+
936
+ endif;
937
+
938
+ // -> taxonomy
939
+ $taxonomies = get_taxonomies( array( 'public' => true, '_builtin' => false ) );
940
+ foreach ($taxonomies as $term_name):
941
+ if ( isset($query[$term_name]) ) {
942
+
943
+ $term_slug = $this->get_last_slash( $query[$term_name] );
944
+ $term = $this->get_term_by('slug', $term_slug, $term_name);
945
+ if (!$term) return $query;
946
+ $cache_array = array($term);
947
+ update_term_cache($cache_array, $term_name); // caching query :)
948
+ $id = $term;
949
+ $query[$term_name] = $term->slug;
950
+ $function = 'get_term_link';
951
+
952
  }
953
+ endforeach;
954
+
955
+ // -> home url
956
+ if ( empty($query) ):
957
+
958
+ $function = 'home_url';
959
+ $id = '';
960
+
961
+ endif;
962
+
963
+ if ( isset($function) ):
964
+
965
+ // parse all languages links
966
+ foreach( $q_config['enabled_languages'] as $lang ) {
967
+
968
+ $this->lang = $lang;
969
+ $this->current_url[$lang] = apply_filters('qts_url_args', call_user_func($function, $id));
970
+
971
+ }
972
+ $this->lang = false;
973
+
974
+ endif;
975
+
976
+ return $query;
977
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
978
 
 
979
 
 
980
 
981
+ /**
982
+ * Parse a hierarquical name and extract the last one
983
+ *
984
+ * @param string $lang Page path
985
+ * @return string
986
+ *
987
+ * @since 1.0
988
+ */
989
+ public function get_current_url( $lang = false ) {
990
+ global $q_config;
991
+
992
+ if (!$lang) $lang = $this->get_lang();
993
+
994
+ if (isset($this->current_url[$lang]) && !empty($this->current_url[$lang]))
995
+ return $this->current_url[$lang];
996
+
997
+ return '';
998
+ }
999
+
1000
+
1001
 
1002
+ /**
1003
+ * Parse a hierarquical name and extract the last one
1004
+ *
1005
+ * @param string $slug Page path
1006
+ * @return string
1007
+ *
1008
+ * @since 1.0
1009
+ */
1010
+ private function get_last_slash($slug) {
1011
+
1012
+ $slug = rawurlencode( urldecode( $slug ) );
1013
+ $slug = str_replace('%2F', '/', $slug);
1014
+ $slug = str_replace('%20', ' ', $slug);
1015
+
1016
+ return array_pop( explode('/', $slug) );
1017
  }
1018
 
1019
+
1020
+
1021
+ /**
1022
+ * Retrieves a page id given its path.
1023
+ *
1024
+ * @param string $page_path Page path
1025
+ * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
1026
+ * @param string $post_type Optional. Post type. Default page.
1027
+ * @return mixed Null when complete.
1028
+ *
1029
+ * @since 1.0
1030
+ */
1031
+ private function get_page_id_by_path($page_path, $output = OBJECT, $post_type = 'page') {
1032
+ global $wpdb;
1033
+
1034
+ $page_path = rawurlencode(urldecode($page_path));
1035
+ $page_path = str_replace('%2F', '/', $page_path);
1036
+ $page_path = str_replace('%20', ' ', $page_path);
1037
+ $parts = explode( '/', trim( $page_path, '/' ) );
1038
+ $parts = array_map( 'esc_sql', $parts );
1039
+ $parts = array_map( 'sanitize_title_for_query', $parts );
1040
+
1041
+ $in_string = "'". implode( "','", $parts ) . "'";
1042
+ $meta_key = $this->get_meta_key();
1043
+ $post_type_sql = $post_type;
1044
+ $wpdb->escape_by_ref( $post_type_sql );
1045
+
1046
+ $pages = $wpdb->get_results( "SELECT $wpdb->posts.ID, $wpdb->posts.post_parent, $wpdb->postmeta.meta_value FROM $wpdb->posts,$wpdb->postmeta WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = '$meta_key' AND $wpdb->postmeta.meta_value IN ($in_string) AND ($wpdb->posts.post_type = '$post_type_sql' OR $wpdb->posts.post_type = 'attachment')", OBJECT_K );
1047
+
1048
+ $revparts = array_reverse( $parts );
1049
+
1050
+ $foundid = 0;
1051
+ foreach ( (array) $pages as $page ) {
1052
+ if ( $page->meta_value == $revparts[0] ) {
1053
+ $count = 0;
1054
+ $p = $page;
1055
+ while ( $p->post_parent != 0 && isset( $pages[ $p->post_parent ] ) ) {
1056
+ $count++;
1057
+ $parent = $pages[ $p->post_parent ];
1058
+ if ( ! isset( $revparts[ $count ] ) || $parent->meta_value != $revparts[ $count ] )
1059
+ break;
1060
+ $p = $parent;
1061
+ }
1062
+
1063
+ if ( $p->post_parent == 0 && $count+1 == count( $revparts ) && $p->meta_value == $revparts[ $count ] ) {
1064
+ $foundid = $page->ID;
1065
+ break;
1066
+ }
1067
  }
1068
  }
1069
+
1070
+ if ( $foundid ) {
1071
+
1072
+ return $foundid;
1073
+
1074
+ } else {
1075
+
1076
+ $last_part = array_pop($parts);
1077
+ $page_id = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE post_name = '$last_part' AND (post_type = '$post_type_sql' OR post_type = 'attachment')" );
1078
+
1079
+ if ( $page_id )
1080
+ return $page_id;
1081
  }
1082
 
1083
+ return null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1084
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1085
 
1086
+
1087
+
1088
+
1089
+ /**
1090
+ * Retrieves a page given its path.
1091
+ *
1092
+ * @param string $page_path Page path
1093
+ * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
1094
+ * @param string $post_type Optional. Post type. Default page.
1095
+ * @return mixed Null when complete.
1096
+ *
1097
+ * @since 1.0
1098
+ */
1099
+ private function get_page_by_path($page_path, $output = OBJECT, $post_type = 'page') {
1100
+ $foundid = $this->get_page_id_by_path($page_path, $output, $post_type);
1101
+ if ( $foundid )
1102
+ return get_page( $foundid, $output );
1103
+
1104
+ return null;
1105
+ }
1106
+
1107
+
1108
+
1109
+ /**
1110
+ * Ignores if the mod_rewrite func is the caller
1111
+ *
1112
+ * @return boolean
1113
+ *
1114
+ * @since 1.0
1115
+ */
1116
+ private function ignore_rewrite_caller() {
1117
+
1118
+ $backtrace = debug_backtrace();
1119
+
1120
+ $ignore_functions = array('mod_rewrite_rules', 'save_mod_rewrite_rules', 'flush_rules', 'rewrite_rules', 'wp_rewrite_rules');
1121
+
1122
+ if ( isset($backtrace['function']) ) {
1123
+ if (in_array($backtrace['function'], $ignore_functions)) return true;
1124
+ } else {
1125
+ foreach ($backtrace as $trace) if ( isset($trace['function']) && in_array($trace['function'], $ignore_functions) ) return true;
1126
+ }
1127
+
1128
+ return false;
1129
+ }
1130
+
1131
+
1132
+ /**
1133
+ * Retrieve the home url for a given site.
1134
+ *
1135
+ * @param int $blog_id (optional) Blog ID. Defaults to current blog.
1136
+ * @param string $path (optional) Path relative to the home url.
1137
+ * @param string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https'.
1138
+ * @return string Home url link with optional path appended.
1139
+ *
1140
+ * @since 1.0
1141
+ */
1142
+ public function home_url($url, $path, $scheme, $blog_id) {
1143
+
1144
+ if ( !in_array( $scheme, array( 'http', 'https' ) ) )
1145
+ $scheme = is_ssl() && !is_admin() ? 'https' : 'http';
1146
+
1147
+ if ( empty( $blog_id ) || !is_multisite() )
1148
+ $url = get_option( 'home' );
1149
+ else
1150
+ $url = get_blog_option( $blog_id, 'home' );
1151
+
1152
+ if ( 'http' != $scheme )
1153
+ $url = str_replace( 'http://', "$scheme://", $url );
1154
+
1155
+ $ignore_caller = $this->ignore_rewrite_caller();
1156
+
1157
+ if ( !empty( $path ) && is_string( $path ) && strpos( $path, '..' ) === false )
1158
+ $url .= '/' . ltrim( $path, '/' );
1159
+
1160
+ if ( !$ignore_caller )
1161
+ $url = qtrans_convertURL($url, $this->get_lang(), true);
1162
+
1163
+ return $url;
1164
+ }
1165
+
1166
+
1167
+
1168
+ /**
1169
+ * Filter that changes the permastruct depending
1170
+ *
1171
+ * @param string $permastruct default permastruct given b wp_rewrite
1172
+ * @param string $name the name of the extra permastruct
1173
+ * @return string processed permastruct
1174
+ *
1175
+ * @since 1.0
1176
+ */
1177
+ public function get_extra_permastruct( $permastruct = false, $name = false ) {
1178
+
1179
+ if ( !$name || !$permastruct ) return '';
1180
+
1181
+ if ( $base = $this->get_base_slug($name, $this->get_lang()) )
1182
+ return "/$base/%$name%";
1183
+
1184
+ return $permastruct;
1185
+ }
1186
+
1187
+
1188
+
1189
+ /**
1190
+ * Filter that translates the slug parts in a page link
1191
+ *
1192
+ * @param $link the link for the page generated by Wordpress
1193
+ * @param $id the id of the page
1194
+ * @return the link translated
1195
+ *
1196
+ * @since 1.0
1197
+ */
1198
+ public function post_type_link( $link, $post, $leavename, $sample ) {
1199
+ global $wp_rewrite;
1200
 
1201
+ if ( is_wp_error( $post ) )
1202
+ return $post;
 
1203
 
1204
+ $post_link = apply_filters( 'qts_permastruct', $wp_rewrite->get_extra_permastruct($post->post_type), $post->post_type);
1205
+
1206
+ $slug = get_post_meta( $post->ID, $this->get_meta_key(), true );
1207
+ if (!$slug) $slug = $post->post_name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1208
 
1209
+ $draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
 
 
 
 
 
 
1210
 
1211
+ $post_type = get_post_type_object($post->post_type);
1212
 
1213
+ if ( !empty($post_link) && ( !$draft_or_pending || $sample ) ) {
1214
+ if ( ! $leavename ) {
1215
+ if ( $post_type->hierarchical )
1216
+ $slug = $this->get_page_uri($post->ID);
1217
+ $post_link = str_replace("%$post->post_type%", $slug, $post_link);
1218
+ }
1219
+
1220
+ $post_link = home_url( user_trailingslashit($post_link) );
1221
+
1222
+ } else {
1223
+
1224
+ if ( $post_type->query_var && ( isset($post->post_status) && !$draft_or_pending ) )
1225
+ $post_link = add_query_arg($post_type->query_var, $slug, '');
1226
+ else
1227
+ $post_link = add_query_arg(array('post_type' => $post->post_type, 'p' => $post->ID), '');
1228
+
1229
+ $post_link = home_url($post_link);
1230
+ }
1231
 
1232
+ return $post_link;
1233
+ }
1234
+
1235
+
1236
 
1237
+ /**
1238
+ * Filter that translates the slug in a post link
1239
+ *
1240
+ * @param $link the link generated by wordpress
1241
+ * @param $post the post data
1242
+ * @param $leavename parameter used by get_permalink. Whether to keep post name or page name.
1243
+ * @return the link translated
1244
+ *
1245
+ * @since 1.0
1246
+ */
1247
+ public function post_link( $link, $post, $leavename ) {
1248
+ global $q_config;
1249
 
1250
+ $rewritecode = array(
1251
+ '%year%',
1252
+ '%monthnum%',
1253
+ '%day%',
1254
+ '%hour%',
1255
+ '%minute%',
1256
+ '%second%',
1257
+ $leavename? '' : '%postname%',
1258
+ '%post_id%',
1259
+ '%category%',
1260
+ '%author%',
1261
+ $leavename? '' : '%pagename%',
1262
+ );
1263
+
1264
+ if ( empty($post->ID) )
1265
+ return false;
1266
+
1267
+ $permalink = $this->permalink_structure;
1268
+
1269
+ if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {
1270
+ $unixtime = strtotime($post->post_date);
1271
+
1272
+ $category = '';
1273
+ if ( strpos($permalink, '%category%') !== false ) {
1274
+ $cats = get_the_category($post->ID);
1275
+ if ( $cats ) {
1276
+ usort($cats, '_usort_terms_by_ID'); // order by ID
1277
+
1278
+ $category = get_term_meta($cats[0]->term_id, $this->get_meta_key(), true );
1279
+ if (!$category) $category = $cats[0]->slug;
1280
+
1281
+ if ( $parent = $cats[0]->parent )
1282
+ $category = $this->get_category_parents($parent, false, '/', true) . $category;
1283
  }
1284
+ // show default category in permalinks, without
1285
+ // having to assign it explicitly
1286
+ if ( empty($category) ) {
1287
+ $default_category = get_category( get_option( 'default_category' ) );
1288
+
1289
+ $default_category_slug = get_term_meta($default_category->term_id, $this->get_meta_key(), true );
1290
+ if (!$default_category_slug) $default_category_slug = $default_category->slug;
1291
+
1292
+ $category = is_wp_error( $default_category ) ? '' : $default_category_slug;
1293
  }
1294
  }
1295
+
1296
+ $author = '';
1297
+ if ( strpos($permalink, '%author%') !== false ) {
1298
+ $authordata = get_userdata($post->post_author);
1299
+ $author = $authordata->user_nicename;
1300
+ }
1301
+
1302
+ $date = explode(" ",date('Y m d H i s', $unixtime));
1303
+
1304
+ $post_slug = get_post_meta($post->ID, $this->get_meta_key(), true );
1305
+ if(!$post_slug) $post_slug = $post->post_name;
1306
+
1307
+ $rewritereplace =
1308
+ array(
1309
+ $date[0],
1310
+ $date[1],
1311
+ $date[2],
1312
+ $date[3],
1313
+ $date[4],
1314
+ $date[5],
1315
+ $post_slug,
1316
+ $post->ID,
1317
+ $category,
1318
+ $author,
1319
+ $post_slug,
1320
+ );
1321
+ $permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink));
1322
+ if ($q_config['url_mode'] != 1)
1323
+ $permalink = user_trailingslashit($permalink, 'single');
1324
+ } else { // if they're not using the fancy permalink option
1325
+ $permalink = home_url('?p=' . $post->ID);
1326
  }
1327
+
1328
+ return $permalink;
1329
  }
1330
 
 
1331
 
1332
+
1333
+ /**
1334
+ * Retrieve category parents with separator.
1335
+ *
1336
+ * @param int $id Category ID.
1337
+ * @param bool $link Optional, default is false. Whether to format with link.
1338
+ * @param string $separator Optional, default is '/'. How to separate categories.
1339
+ * @param bool $nicename Optional, default is false. Whether to use nice name for display.
1340
+ * @param array $visited Optional. Already linked to categories to prevent duplicates.
1341
+ * @return string
1342
+ *
1343
+ * @since 1.0
1344
+ */
1345
+ private function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
1346
+
1347
+ $chain = '';
1348
+ $parent = &get_category( $id );
1349
+ if ( is_wp_error( $parent ) )
1350
+ return $parent;
1351
 
1352
+ if ( $nicename ) {
1353
+
1354
+ $name = get_term_meta($parent->term_id, $this->get_meta_key(), true );
1355
+ if (!$name) $name = $parent->slug;
1356
+ } else {
1357
+ $name = $parent->name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1358
  }
1359
 
1360
+ if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
1361
+ $visited[] = $parent->parent;
1362
+ $chain .= $this->get_category_parents( $parent->parent, $link, $separator, $nicename, $visited );
1363
  }
1364
+
1365
+ if ( $link )
1366
+ $chain .= '<a href="' . get_category_link( $parent->term_id ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $parent->name ) ) . '">'.$name.'</a>' . $separator;
1367
+ else
1368
+ $chain .= $name.$separator;
1369
+
1370
+ return $chain;
1371
  }
1372
+
1373
 
1374
+
1375
+
1376
+
1377
+ /**
1378
+ * Filter that translates the slug parts in a page link
1379
+ *
1380
+ * @param $link the link for the page generated by Wordpress
1381
+ * @param $id the id of the page
1382
+ * @return the link translated
1383
+ *
1384
+ * @since 1.0
1385
+ */
1386
+ public function _get_page_link( $link, $id ) {
1387
+ global $post, $wp_rewrite, $q_config;
1388
 
1389
+ if ( !$id )
1390
+ $id = (int) $post->ID;
1391
+ else
1392
+ $post = &get_post($id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393
 
1394
+ $draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1395
 
1396
+ $link = $wp_rewrite->get_page_permastruct();
1397
 
1398
+ if ( !empty($link) && ( isset($post->post_status) && !$draft_or_pending ) ) {
1399
+
1400
+ $link = str_replace('%pagename%', $this->get_page_uri($id), $link);
1401
+
1402
+ $link = trim($link, '/'); // hack
1403
+ $link = home_url("/$link/"); // hack
1404
+
1405
+ if ($q_config['url_mode'] != 1)
1406
+ $link = user_trailingslashit($link, 'page');
1407
+
1408
+ } else {
1409
+
1410
+ $link = home_url("?page_id=$id");
1411
+ }
1412
 
1413
+ return $link;
1414
+ }
1415
+
1416
+
1417
+
1418
+ /**
1419
+ * Builds URI for a page.
1420
+ *
1421
+ * Sub pages will be in the "directory" under the parent page post name.
1422
+ *
1423
+ * @param mixed $page Page object or page ID.
1424
+ * @return string Page URI.
1425
+ *
1426
+ * @since 1.0
1427
+ */
1428
+ private function get_page_uri($page) {
1429
+
1430
+ if ( ! is_object($page) )
1431
+ $page = get_page($page);
1432
+
1433
+ $uri = get_post_meta( $page->ID, $this->get_meta_key(), true );
1434
+ if (!$uri) $uri = $page->post_name;
1435
 
1436
+ // A page cannot be it's own parent.
1437
+ if ( $page->post_parent == $page->ID )
1438
+ return $uri;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1439
 
1440
+ while ($page->post_parent != 0) {
1441
+ $page = get_page($page->post_parent);
1442
+
1443
+ $page_name = get_post_meta( $page->ID, $this->get_meta_key(), true );
1444
+ if (!$page_name) $page_name = $page->post_name;
1445
+
1446
+ $uri = $page_name . "/" . $uri;
1447
+ }
1448
 
1449
+ return $uri;
 
 
 
 
 
 
 
1450
  }
1451
+
1452
+
1453
+
1454
+ /**
1455
+ * Filter that translates the slug parts in a term link
1456
+ *
1457
+ * @param $link the link for the page generated by Wordpress
1458
+ * @param $term object
1459
+ * @param $taxonomy object
1460
+ * @return the link translated
1461
+ *
1462
+ * @since 1.0
1463
+ */
1464
+ public function term_link( $link, $term, $taxonomy ) {
1465
+ global $wp_rewrite;
1466
 
1467
+ // parse normal term names for ?tag=tagname
1468
+ if (empty($this->permalink_structure)) return $link;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1469
 
1470
+ if ( !is_object($term) ) {
1471
+ if ( is_int($term) ) {
1472
+ $term = &get_term($term, $taxonomy);
1473
+ } else {
1474
+ $term = $this->get_term_by('slug', $term, $taxonomy);
1475
+ }
1476
+ }
1477
 
1478
+ if ( !is_object($term) )
1479
+ $term = new WP_Error('invalid_term', __('Empty Term'));
1480
 
1481
+ if ( is_wp_error( $term ) )
1482
+ return $term;
 
 
 
 
 
 
 
 
 
 
1483
 
1484
+ $taxonomy = $term->taxonomy;
 
1485
 
1486
+ $termlink = apply_filters( 'qts_permastruct', $wp_rewrite->get_extra_permastruct($taxonomy), $taxonomy);
1487
+
1488
+ $slug = get_term_meta( $term->term_id, $this->get_meta_key(), true );
1489
+ if (!$slug) $slug = $term->slug;
1490
+
1491
+ $t = get_taxonomy($taxonomy);
1492
+
1493
+ if ( empty($termlink) ) {
1494
+ if ( 'category' == $taxonomy )
1495
+ $termlink = '?cat=' . $term->term_id;
1496
+ elseif ( $t->query_var )
1497
+ $termlink = "?$t->query_var=$slug";
1498
+ else
1499
+ $termlink = "?taxonomy=$taxonomy&term=$slug";
1500
+ $termlink = home_url($termlink);
1501
+ } else {
1502
+ if ( $t->rewrite['hierarchical'] ) {
1503
+ $hierarchical_slugs = array();
1504
+ $ancestors = get_ancestors($term->term_id, $taxonomy);
1505
+ foreach ( (array)$ancestors as $ancestor ) {
1506
+ $ancestor_term = get_term($ancestor, $taxonomy);
1507
+
1508
+ $ancestor_slug = get_term_meta( $ancestor_term->term_id, $this->get_meta_key(), true );
1509
+ if (!$ancestor_slug) $ancestor_slug = $ancestor_term->slug;
1510
+
1511
+ $hierarchical_slugs[] = $ancestor_slug;
1512
+ }
1513
+ $hierarchical_slugs = array_reverse($hierarchical_slugs);
1514
+ $hierarchical_slugs[] = $slug;
1515
+ $termlink = str_replace("%$taxonomy%", implode('/', $hierarchical_slugs), $termlink);
1516
+ } else {
1517
+ $termlink = str_replace("%$taxonomy%", $slug, $termlink);
1518
+ }
1519
+ $termlink = home_url( user_trailingslashit($termlink, 'category') );
1520
+ }
1521
+ return $termlink;
1522
+ }
1523
+
1524
+
1525
+
1526
+ /**
1527
+ * Get all Term data from database by Term field and data.
1528
+ *
1529
+ * @param string $field Either 'slug', 'name', or 'id'
1530
+ * @param string|int $value Search for this term value
1531
+ * @param string $taxonomy Taxonomy Name
1532
+ * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
1533
+ * @param string $filter Optional, default is raw or no WordPress defined filter will applied.
1534
+ * @return mixed Term Row from database. Will return false if $taxonomy does not exist or $term was not found.
1535
+ *
1536
+ * @since 1.0
1537
+ */
1538
+ private function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') {
1539
+ global $wpdb;
1540
+
1541
+ $original_field = $field;
1542
+
1543
+ if ( ! taxonomy_exists($taxonomy) )
1544
+ return false;
1545
+
1546
+ if ( 'slug' == $field ) {
1547
+ $field = 'm.meta_key = \''.$this->get_meta_key().'\' AND m.meta_value';
1548
+ $value = sanitize_title($value);
1549
+ if ( empty($value) )
1550
+ return false;
1551
+ } else if ( 'name' == $field ) {
1552
+ // Assume already escaped
1553
+ $value = stripslashes($value);
1554
+ $field = 't.name';
1555
+ } else {
1556
+ $term = get_term( (int) $value, $taxonomy, $output, $filter);
1557
+ if ( is_wp_error( $term ) )
1558
+ $term = false;
1559
+ return $term;
1560
+ }
1561
+
1562
+ $term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt, $wpdb->termmeta AS m WHERE t.term_id = tt.term_id AND tt.term_id = m.term_id AND tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) );
1563
 
1564
+ if ( !$term && 'slug' == $original_field ) {
1565
+ $field = 't.slug';
1566
+ $term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1567
  }
1568
+
1569
+ if ( !$term )
1570
+ return false;
1571
+
1572
+ wp_cache_add($term->term_id, $term, $taxonomy);
1573
+
1574
+ $term = apply_filters('get_term', $term, $taxonomy);
1575
+ $term = apply_filters("get_$taxonomy", $term, $taxonomy);
1576
+ $term = sanitize_term($term, $taxonomy, $filter);
1577
+
1578
+ if ( $output == OBJECT ) {
1579
+ return $term;
1580
+ } elseif ( $output == ARRAY_A ) {
1581
+ return get_object_vars($term);
1582
+ } elseif ( $output == ARRAY_N ) {
1583
+ return array_values(get_object_vars($term));
1584
+ } else {
1585
+ return $term;
1586
  }
1587
+ }
1588
+
1589
+
1590
+
1591
+ /**
1592
+ * hide quickedit button ( functionality not supported by qTranslate )
1593
+ *
1594
+ * @since 1.0
1595
+ */
1596
+ public function hide_quick_edit() {
1597
+ echo "<!-- QTS remove quick edit box -->" . PHP_EOL;
1598
+ echo "<style type=\"text/css\" media=\"screen\">" . PHP_EOL;
1599
+ echo " .row-actions .inline.inline.hide-if-no-js { display: none !important }" . PHP_EOL;
1600
+ echo "</style>" . PHP_EOL;
1601
+ }
1602
+
1603
+
1604
+
1605
+ /**
1606
+ * Hide auttomatically the wordpress slug blog in edit posts page
1607
+ *
1608
+ * @since 1.0
1609
+ */
1610
+ public function hide_slug_box() {
1611
+ global $pagenow;
1612
+
1613
+ switch ( $pagenow ):
1614
+ case 'edit-tags.php':
1615
+
1616
+ echo "<!-- QTS remove slug box -->" . PHP_EOL;
1617
+ echo "<script type=\"text/javascript\" charset=\"utf-8\">" . PHP_EOL;
1618
+ echo " jQuery(document).ready(function($){" . PHP_EOL;
1619
+ echo " $(\"#tag-slug\").parent().hide();" . PHP_EOL;
1620
+ echo " $(\".form-field td #slug\").parent().parent().hide();" . PHP_EOL;
1621
+ echo " });" . PHP_EOL;
1622
+ echo "</script>" . PHP_EOL;
1623
+ break;
1624
+
1625
+ case 'post.php':
1626
+
1627
+ echo "<!-- QTS remove slug box -->" . PHP_EOL;
1628
+ echo "<style type=\"text/css\" media=\"screen\">" . PHP_EOL;
1629
+ echo " #edit-slug-box { display: none !important}" . PHP_EOL;
1630
+ echo "</style>" . PHP_EOL;
1631
+ break;
1632
+ endswitch;
1633
+ }
1634
+
1635
+
1636
+
1637
+ /**
1638
+ * Creates a metabox for every post, page and post type avaiable
1639
+ *
1640
+ * @since 1.0
1641
+ */
1642
+ public function add_slug_meta_box() {
1643
+
1644
+ if ( function_exists( 'add_meta_box' ) ) {
1645
+
1646
+ add_meta_box( 'qts_sectionid', __('Slug', 'qts'), array($this, 'draw_meta_box'), 'post', 'side', 'high');
1647
+ add_meta_box( 'qts_sectionid', __('Slug', 'qts'), array($this, 'draw_meta_box'), 'page', 'side', 'high' );
1648
+
1649
+ foreach ( get_post_types( array('_builtin' => false ) ) as $ptype )
1650
+ add_meta_box( 'qts_sectionid', __('Slug', 'qts'), array($this, 'draw_meta_box'), $ptype, 'side', 'high' );
1651
  }
 
 
1652
  }
1653
+
1654
+
1655
+
1656
+ /**
1657
+ * Shows the fields where insert the translated slugs in the post and page edit form.
1658
+ *
1659
+ * @param $post (object) current post object
1660
+ *
1661
+ * @since 1.0
1662
+ */
1663
+ public function draw_meta_box( $post ) {
1664
+ global $q_config;
1665
+
1666
+ // Use nonce for verification
1667
+ echo "<table style=\"width:100%\">" . PHP_EOL;
1668
+ echo "<input type=\"hidden\" name=\"qts_nonce\" id=\"qts_nonce\" value=\"" . wp_create_nonce( 'qts_nonce' ) . "\" />" . PHP_EOL;
1669
+
1670
+ foreach ($q_config['enabled_languages'] as $lang):
1671
+
1672
+ $slug = get_post_meta( $post->ID, $this->get_meta_key($lang), true);
1673
+
1674
+ $value = ( $slug ) ? htmlspecialchars( $slug , ENT_QUOTES ) : '';
1675
+
1676
+ echo "<tr>" . PHP_EOL;
1677
+ echo "<th style=\"text-align:left; width:10%; color:#555 \"><label for=\"qts_{$lang}_slug\">".__($q_config['language_name'][$lang], 'qtranslate')."</label></th>" . PHP_EOL;
1678
+ echo "<td><input type=\"text\" id=\"qts_{$lang}_slug\" name=\"qts_{$lang}_slug\" value=\"$value\" style=\"width:90%; margin-left:10%; color:#777\" /></td>" . PHP_EOL;
1679
+ echo "</tr>" . PHP_EOL;
1680
+
1681
+ endforeach;
1682
+
1683
+ echo '</table>' . PHP_EOL;
1684
  }
1685
 
1686
+
1687
+
1688
+ /**
1689
+ * Sanitize title as slug, if empty slug
1690
+ *
1691
+ * @param $post (object) the post object
1692
+ * @param $slug (string) the slug name
1693
+ * @param $lang (string) the language
1694
+ * @return the slug validated
1695
+ *
1696
+ * @since 1.0
1697
+ */
1698
+ public function validate_post_slug( $slug, $post, $lang ) {
1699
+
1700
+ $post_title = trim(qtrans_use($lang, $_POST['post_title']));
1701
+ $post_name = get_post_meta($post->ID, $this->get_meta_key($lang), true);
1702
+ if (!$post_name) $post_name = $post->post_name;
1703
 
1704
+ $name = ( $post_title == '' || strlen($post_title) == 0 ) ? $post_name : $post_title;
1705
+
1706
+ $slug = trim($slug);
1707
+
1708
+ $slug = (empty($slug)) ? sanitize_title($name) : sanitize_title($slug);
1709
+
1710
+
1711
+
1712
+ return htmlspecialchars( $slug , ENT_QUOTES );
1713
  }
1714
 
1715
+
1716
+
1717
+ /**
1718
+ * Validates post slug against repetitions per language
1719
+ *
1720
+ * @param $post (object) the post object
1721
+ * @param $slug (string) the slug name
1722
+ * @param $lang (string) the language
1723
+ * @return the slug validated
1724
+ *
1725
+ * @since 1.0
1726
+ */
1727
+ public function unique_post_slug( $slug, $post, $lang ) {
1728
+
1729
+ $original_status = $post->post_status;
1730
+
1731
+ if ( in_array($post->post_status, array('draft', 'pending')) )
1732
+ $post->post_status = 'publish';
1733
+
1734
+ $slug = $this->wp_unique_post_slug( $slug, $post->ID, $post->post_status, $post->post_type, $post->post_parent, $lang );
1735
+
1736
+ $post->post_status = $original_status;
1737
+
1738
+ return $slug;
1739
+ }
1740
+
1741
+
1742
+
1743
+ /**
1744
+ * Computes a unique slug for the post and language, when given the desired slug and some post details.
1745
+ *
1746
+ * @param string $slug the desired slug (post_name)
1747
+ * @param integer $post_ID
1748
+ * @param string $post_status no uniqueness checks are made if the post is still draft or pending
1749
+ * @param string $post_type
1750
+ * @param integer $post_parent
1751
+ * @return string unique slug for the post, based on language meta_value (with a -1, -2, etc. suffix)
1752
+ *
1753
+ * @since 1.0
1754
+ */
1755
+ public function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $lang ) {
1756
+ if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) )
1757
+ return $slug;
1758
+
1759
+ global $wpdb, $wp_rewrite;
1760
+
1761
+ $feeds = $wp_rewrite->feeds;
1762
+ if ( ! is_array( $feeds ) )
1763
+ $feeds = array();
1764
+
1765
+ $meta_key = $this->get_meta_key($lang);
1766
+ if ( 'attachment' == $post_type ) {
1767
+ // Attachment slugs must be unique across all types.
1768
+ $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
1769
+ $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) );
1770
+
1771
+ if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_attachment_slug', false, $slug ) ) {
1772
+ $suffix = 2;
1773
+ do {
1774
+ $alt_post_name = substr ($slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
1775
+ $post_name_check = $wpdb->get_var( $wpdb->prepare($check_sql, $alt_post_name, $post_ID ) );
1776
+ $suffix++;
1777
+ } while ( $post_name_check );
1778
+ $slug = $alt_post_name;
1779
+ }
1780
+ } else {
1781
+ // Post slugs must be unique across all posts.
1782
+ $check_sql = "SELECT $wpdb->postmeta.meta_value FROM $wpdb->posts,$wpdb->postmeta WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = '%s' AND $wpdb->postmeta.meta_value = '%s' AND $wpdb->posts.post_type = %s AND ID != %d LIMIT 1";
1783
+ $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $meta_key, $slug, $post_type, $post_ID ) );
1784
+
1785
+ if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) {
1786
+ $suffix = 2;
1787
+ do {
1788
+ $alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
1789
+ $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $meta_key, $alt_post_name, $post_type, $post_ID ) );
1790
+ $suffix++;
1791
+ } while ( $post_name_check );
1792
+ $slug = $alt_post_name;
1793
+ }
1794
+ }
1795
 
1796
+ return $slug;
1797
  }
1798
 
1799
+
1800
+
1801
+
1802
+ /**
1803
+ * Saves the translated slug when the page is saved
1804
+ *
1805
+ * @param $post_id the post id
1806
+ * @param $post the post object
1807
+ *
1808
+ * @since 1.0
1809
+ */
1810
+ public function save_postdata( $post_id, $post ) {
1811
+ global $q_config;
1812
+
1813
+ $post_type_object = get_post_type_object( $post->post_type);
1814
+
1815
+
1816
+ if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) // check autosave
1817
+ || (!isset($_POST['post_ID']) || $post_id != $_POST['post_ID']) // check revision
1818
+ || (!wp_verify_nonce( $_POST['qts_nonce'], 'qts_nonce')) // verify nonce
1819
+ || (!current_user_can($post_type_object->cap->edit_post, $post_id))) { // check permission
1820
+ return $post_id;
1821
+ }
1822
+
1823
+ foreach ($q_config['enabled_languages'] as $lang):
1824
+
1825
+ $meta_name = $this->get_meta_key($lang);
1826
+ $meta_value = apply_filters( 'qts_validate_post_slug', $_POST["qts_{$lang}_slug"], $post, $lang);
1827
+
1828
+ delete_post_meta($post_id, $meta_name);
1829
+ update_post_meta($post_id, $meta_name, $meta_value);
1830
+
1831
+ endforeach;
1832
  }
1833
+
1834
+
1835
+
1836
+ /**
1837
+ * Display multiple input fields, one per language
1838
+ *
1839
+ * @param $term the term object
1840
+ *
1841
+ * @since 1.0
1842
+ */
1843
+ public function show_term_fields( $term ) {
1844
+ global $q_config;
1845
+
1846
+ // prints the fields in edit page
1847
+ if (isset($_GET['action']) && $_GET['action'] == 'edit' ):
1848
+
1849
+ echo "<table class=\"form-table\">" . PHP_EOL;
1850
+ echo "<input type=\"hidden\" name=\"qts_nonce\" id=\"qts_nonce\" value=\"" . wp_create_nonce( 'qts_nonce' ) . "\" />" . PHP_EOL;
1851
+
1852
+ foreach( $q_config['enabled_languages'] as $lang ):
1853
+
1854
+ $slug = (is_object($term)) ? get_term_meta( $term->term_id, $this->get_meta_key($lang), true ) : '';
1855
+
1856
+ $value = ( $slug ) ? htmlspecialchars( $slug , ENT_QUOTES ) : '';
1857
+
1858
+ echo "<tr class=\"form-field form-required\">" . PHP_EOL;
1859
+ echo "<th scope=\"row\" valig=\"top\"><label for=\"qts_{$lang}_slug\">Slug (".__($q_config['language_name'][$lang], 'qtranslate').")</label></th>" . PHP_EOL;
1860
+ echo "<td><input type=\"text\" name=\"qts_{$lang}_slug\" value=\"$value\" /></td></tr>" . PHP_EOL;
1861
+
1862
+ endforeach;
1863
+
1864
+ echo '</table>';
1865
+
1866
+ // prints the fields in new page
1867
+ else:
1868
+ echo "<input type=\"hidden\" name=\"qts_nonce\" id=\"qts_nonce\" value=\"" . wp_create_nonce( 'qts_nonce' ) . "\" />" . PHP_EOL;
1869
+
1870
+ foreach( $q_config['enabled_languages'] as $lang ):
1871
+
1872
+ echo "<div class=\"form-field\">" . PHP_EOL;
1873
+
1874
+ $slug = (is_object($term)) ? get_term_meta( $term->term_id, $this->get_meta_key($lang), true ) : '';
1875
+
1876
+ $value = ( $slug ) ? htmlspecialchars( $slug , ENT_QUOTES ) : '';
1877
+
1878
 
1879
+ echo "<label for=\"qts_{$lang}_slug\">Slug (".__($q_config['language_name'][$lang], 'qtranslate').")</label>" . PHP_EOL;
1880
+ echo "<input type=\"text\" name=\"qts_{$lang}_slug\" value=\"$value\" aria-required=\"true\">" . PHP_EOL;
1881
+
1882
+ echo '</div>';
1883
+
1884
+ endforeach;
 
 
 
 
 
 
1885
 
1886
+ endif;
 
 
 
 
 
 
 
 
 
1887
  }
1888
+
1889
+
1890
+
1891
+ /**
1892
+ * Sanitize title as slug, if empty slug
1893
+ *
1894
+ * @param $term (object) the term object
1895
+ * @param $slug (string) the slug name
1896
+ * @param $lang (string) the language
1897
+ * @return the slug validated
1898
+ *
1899
+ * @since 1.0
1900
+ */
1901
+ public function validate_term_slug( $slug, $term, $lang ) {
1902
+ global $q_config;
1903
+
1904
+ $lang_name = $q_config['term_name'][$term->name][$lang];
1905
+
1906
+ $ajax_name = 'new' . $term->taxonomy;
1907
+
1908
+ $post_name = isset($_POST['name']) ? $_POST['name'] : '';
1909
+
1910
+ $term_name = isset($_POST[$ajax_name]) ? trim($_POST[$ajax_name]) : $post_name;
1911
+
1912
+ if (empty($term_name)) return $slug;
1913
+
1914
+ $name = ( $lang_name == '' || strlen($lang_name) == 0 ) ? $term_name : $lang_name;
1915
+
1916
+ $slug = trim($slug);
1917
+
1918
+ $slug = (empty($slug)) ? sanitize_title($name) : sanitize_title($slug);
1919
+
1920
+ return htmlspecialchars( $slug , ENT_QUOTES );
1921
+ }
1922
+
1923
+
1924
+
1925
+ /**
1926
+ * Will make slug unique per language, if it isn't already.
1927
+ *
1928
+ * @param string $slug The string that will be tried for a unique slug
1929
+ * @param object $term The term object that the $slug will belong too
1930
+ * @param object $lang The language reference
1931
+ * @return string Will return a true unique slug.
1932
+ *
1933
+ * @since 1.0
1934
+ */
1935
+ public function unique_term_slug($slug, $term, $lang) {
1936
+ global $wpdb;
1937
+
1938
+ $meta_key_name = $this->get_meta_key($lang);
1939
+ $query = "SELECT term_id FROM $wpdb->termmeta WHERE meta_key = '$meta_key_name' AND meta_value = '$slug' AND term_id != $term->term_id ";
1940
+ $exists_slug = $wpdb->get_results($query);
1941
+
1942
+ if ( empty($exists_slug) )
1943
+ return $slug;
1944
+
1945
+ // If we didn't get a unique slug, try appending a number to make it unique.
1946
+ $query = $wpdb->prepare( "SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '$meta_key_name' AND meta_value = '$slug' AND term_id != $term->term_id");
1947
+
1948
+ if ( $wpdb->get_var( $query ) ) {
1949
+ $num = 2;
1950
+ do {
1951
+ $alt_slug = $slug . "-$num";
1952
+ $num++;
1953
+ $slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '$meta_key_name' AND meta_value = '$alt_slug'" ) );
1954
+ } while ( $slug_check );
1955
+ $slug = $alt_slug;
1956
+ }
1957
 
1958
+ return $slug;
1959
+ }
1960
+
1961
+
1962
+
1963
+ /**
1964
+ * Display multiple input fields, one per language
1965
+ *
1966
+ * @param $term_id the term id
1967
+ * @param $tt_id the term taxonomy id
1968
+ * @param $taxonomy the term object
1969
+ *
1970
+ * @since 1.0
1971
+ */
1972
+ public function save_term( $term_id, $tt_id, $taxonomy ) {
1973
+ global $q_config;
1974
+
1975
+ if ( (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) // check autosave
1976
+ || ( !current_user_can('edit_posts') ) ) { // check permission
1977
+ return $term_id;
1978
+ }
1979
+
1980
+ $term = get_term( $term_id, $taxonomy);
1981
+
1982
+ foreach( $q_config['enabled_languages'] as $lang ):
1983
+
1984
+ $meta_name = $this->get_meta_key($lang);
1985
+ $meta_value = apply_filters( 'qts_validate_term_slug', $_POST["qts_{$lang}_slug"], $term, $lang);
1986
+
1987
+ delete_term_meta($term_id, $meta_name);
1988
+ update_term_meta($term_id, $meta_name, $meta_value);
1989
 
1990
+ endforeach;
1991
+ }
 
 
 
 
1992
 
 
 
1993
 
 
 
 
 
1994
 
1995
+ /**
1996
+ * deletes termmeta rows associated with the term
1997
+ *
1998
+ * @since 1.0
1999
+ */
2000
+ public function delete_term($term_id, $tt_id, $taxonomy) {
2001
+ global $wpdb;
2002
+
2003
+ $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->termmeta WHERE term_id = %d", $term_id ) );
2004
+ }
2005
+
2006
+
2007
+
2008
+ /**
2009
+ * adds support for qtranslate in taxonomies
2010
+ *
2011
+ * @since 1.0
2012
+ */
2013
+ public function taxonomies_hooks() {
2014
+
2015
+ $taxonomies = $this->get_public_taxonomies();
2016
 
2017
+ if ($taxonomies) {
2018
+ foreach ($taxonomies as $taxonomy ) {
 
2019
  add_action( $taxonomy->name.'_add_form', 'qtrans_modifyTermFormFor');
2020
  add_action( $taxonomy->name.'_edit_form', 'qtrans_modifyTermFormFor');
2021
+ add_action( $taxonomy->name.'_add_form', array($this, 'show_term_fields'));
2022
+ add_action( $taxonomy->name.'_edit_form_fields', array($this, 'show_term_fields') );
2023
+ add_filter('manage_edit-'.$taxonomy->name.'_columns', array($this, 'taxonomy_columns'));
2024
+ add_filter('manage_'.$taxonomy->name.'_custom_column', array($this, 'taxonomy_custom_column'), 0, 3);
2025
  }
2026
  }
2027
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2028
 
 
2029
 
 
2030
 
2031
+ /*
2032
+ * Bug fix for slug column in taxonomies
2033
+ *
2034
+ * @since 1.0
2035
+ */
2036
+ public function taxonomy_columns($columns) {
2037
+ unset($columns['slug']);
2038
+ unset($columns['posts']);
2039
+
2040
+ $columns['qts-slug'] = __('Slug', 'qts');
2041
+ $columns['posts'] = __('Posts');
2042
+
2043
+ return $columns;
2044
+ }
2045
+
2046
+
2047
+
2048
+ /*
2049
+ * Bug fix for slug column in taxonomies
2050
+ *
2051
+ * @since 1.0
2052
+ */
2053
+ public function taxonomy_custom_column($str, $column_name, $term_id) {
2054
+
2055
+ switch ($column_name) {
2056
+ case 'qts-slug':
2057
+ echo get_term_meta($term_id, $this->get_meta_key(), true);
2058
+ break;
2059
+ }
2060
+ return false;
2061
+ }
2062
+
2063
+
2064
+
2065
+ /**
2066
+ * Bug fix for taxonomy names in wp_terms_list_table
2067
+ *
2068
+ * @param string $name parsed term name
2069
+ * @param object $tag term object
2070
+ * @return string translated term name
2071
+ *
2072
+ * @since 1.0
2073
+ */
2074
+ function term_name($name, $tag) {
2075
+
2076
+ $backtrace = debug_backtrace();
2077
+
2078
+ foreach ( $backtrace as $tracepoint ) {
2079
+
2080
+ // post page column
2081
+ if ( isset($tracepoint['function']) && $tracepoint['function'] == 'sanitize_term_field' ) {
2082
+ return apply_filters('single_term_title', $name);
2083
+ }
2084
+
2085
+ // term page column
2086
+ if ( isset($tracepoint['class']) && $tracepoint['class'] == 'WP_Terms_List_Table' ) {
2087
+ $name_array = explode('&#8212; ', $name);
2088
+ array_pop($name_array);
2089
+ array_push($name_array, apply_filters('single_term_title', $tag->name));
2090
+ return implode('&#8212; ', $name_array);
2091
+ }
2092
+
2093
+ }
2094
+
2095
+ return $name;
2096
+ }
2097
+
2098
+
2099
+
2100
+ /**
2101
+ * Bug fix for multisite blog names
2102
+ *
2103
+ * @since 1.0
2104
+ */
2105
+ public function blog_names($blogs) {
2106
+
2107
+ foreach ($blogs as $blog)
2108
+ $blog->blogname = __($blog->blogname);
2109
+
2110
+ return $blogs;
2111
+ }
2112
+
2113
+
2114
+
2115
+ /**
2116
+ * Initialise the Language Widget selector
2117
+ *
2118
+ * @since 1.0
2119
+ */
2120
+ public function widget_init() {
2121
+
2122
+ if (class_exists('qTranslateWidget'))
2123
+ unregister_widget('qTranslateWidget');
2124
+
2125
+ register_widget('QtranslateSlugWidget');
2126
+ }
2127
+
2128
+
2129
+
2130
+ /**
2131
+ * remove some default dashboard Widgets on Desktop
2132
+ *
2133
+ * @since 1.0
2134
+ */
2135
+ function remove_dashboard_widgets() {
2136
+ global $wp_meta_boxes;
2137
+ unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
2138
+ }
2139
+
2140
+
2141
+
2142
+ /**
2143
+ * adds support for qtranslate nav menus
2144
+ *
2145
+ * @since 1.0
2146
+ */
2147
+ public function fix_nav_menu() {
2148
+ global $pagenow;
2149
+
2150
+ if( $pagenow != 'nav-menus.php' ) return;
2151
+
2152
+ wp_enqueue_script( 'nav-menu-query', plugins_url( 'assets/js/qts-nav-menu-min.js' , __FILE__ ) , 'nav-menu', '1.0' );
2153
+ add_meta_box( 'qt-languages', __('Languages'), array($this, 'nav_menu_meta_box'), 'nav-menus', 'side', 'default' );
2154
+ }
2155
+
2156
+
2157
+
2158
+ /**
2159
+ * draws meta box for select language
2160
+ *
2161
+ * @since 1.0
2162
+ */
2163
+ public function nav_menu_meta_box() {
2164
+ global $q_config;
2165
+ echo '<p>';
2166
+ foreach($q_config['enabled_languages'] as $id => $language) {
2167
+ $checked = ($language == $q_config['language']) ? ' checked="checked"' : '';
2168
+ echo '<p style="margin:0 0 5px 0"><input type="radio" style="margin-right:5px" name="wa_qt_lang" value="' . $language . '" id="wa_gt_lang_' . $id . '" ' . $checked . '/>';
2169
+ echo '<label for="wa_gt_lang_' . $id . '">';
2170
+ echo '<img src="' . trailingslashit(WP_CONTENT_URL).$q_config['flag_location'].$q_config['flag'][$language] . '"/>&nbsp;';
2171
+ echo __($q_config['language_name'][$language], 'qtranslate');
2172
+ echo '</label></p>';
2173
+ }
2174
+ echo '</p>';
2175
+ }
2176
+
2177
+
2178
+
2179
+ /**
2180
+ * Language select function for templating
2181
+ *
2182
+ * @param $type (string) choose the type of menu: 'text', 'image', 'both', 'dropdown'
2183
+ * @param $args (array) some args for draw the menu: array( 'id', 'class', 'short' );
2184
+ *
2185
+ * @since 1.0
2186
+ */
2187
+ public function language_menu( $type = "text", $args = array() ) {
2188
+ global $q_config;
2189
+
2190
+ // default arguments
2191
+ $defaults = array(
2192
+ 'id' => "qts-lang-menu",
2193
+ 'class' => "qts-lang-menu",
2194
+ 'short' => false
2195
+ );
2196
+ $args = wp_parse_args( $args, $defaults );
2197
+
2198
+ $languages = qtrans_getSortedLanguages();
2199
+
2200
+ // every type
2201
+ switch ( $type ) {
2202
+
2203
+ case 'image':
2204
+ case 'text':
2205
+ case 'both':
2206
+
2207
+ echo "<ul id=\"{$args['id']}\" class=\"{$args['class']}\">". PHP_EOL;
2208
+
2209
+ foreach( $languages as $index => $lang ):
2210
+
2211
+ $url = $this->get_current_url($lang);
2212
+
2213
+ $item_class = array();
2214
+ if ( (string)$q_config['language'] == (string)$lang ) $item_class[] = 'current-menu-item';
2215
+ if ( $index == (count($languages) - 1) ) $item_class[] = 'last-child';
2216
+
2217
+ $item_class = empty($item_class) ? '' : ' class="' . implode(' ', $item_class) . '"';
2218
+
2219
+ $language_name = ($args['short']) ? $lang : $q_config['language_name'][$lang];
2220
+
2221
+ if ( $type == 'image' ) {
2222
+ $link_class = " class=\"qtrans_flag qtrans_flag_$lang\"";
2223
+ $link_content = "<span style=\"display:none\">$language_name</span>";
2224
+ } else if ( $type == 'both' ) {
2225
+ $link_class = " class=\"qtrans_flag qtrans_flag_$lang\" style=\"padding-left:25px\"";
2226
+ $link_content = "$language_name";
2227
+
2228
+ } else {
2229
+ $link_class = '';
2230
+ $link_content = $language_name;
2231
+ }
2232
+
2233
+ echo "<li$item_class><a href=\"$url\" hreflang=\"$lang\"$link_class>$link_content</a></li>" . PHP_EOL;
2234
+
2235
+ endforeach;
2236
+
2237
+ echo "</ul>". PHP_EOL;
2238
+
2239
+ break;
2240
+
2241
+ case 'dropdown':
2242
+
2243
+ echo "<select id=\"{$args['id']}\" class=\"{$args['class']}\" onchange=\"window.location.href=this.options[this.selectedIndex].value\">". PHP_EOL;
2244
+
2245
+ foreach( $languages as $index => $lang ):
2246
+
2247
+ $url = $this->get_current_url($lang);
2248
+
2249
+ $item_class = '';
2250
+ if ( (string)$q_config['language'] == (string)$lang ) $item_class = 'selected="selected"';
2251
+
2252
+ $language_name = ($args['short']) ? $lang : $q_config['language_name'][$lang];
2253
+
2254
+ echo "<option value=\"$url\" $item_class>$language_name</option>" . PHP_EOL;
2255
+
2256
+ endforeach;
2257
+
2258
+ echo "</select>". PHP_EOL;
2259
+
2260
+ break;
2261
+ }
2262
+
2263
  }
2264
  }
2265
+ ////////////////////////////////////////////////////////////////////////////////////////
2266
+
2267
+
2268
 
2269
  /**
2270
+ * Define Constants
2271
+ *
2272
+ * @since 1.0
2273
+ */
2274
+ if (!defined("QTS_VERSION")) define("QTS_VERSION", '1.0');
2275
+ if (!defined("QTS_PREFIX")) define("QTS_PREFIX", '_qts_');
2276
+ if (!defined("QTS_PAGE_BASENAME")) define('QTS_PAGE_BASENAME', 'qtranslate-slug-settings');
2277
+ if (!defined("QTS_OPTIONS_NAME")) define("QTS_OPTIONS_NAME", 'qts_options');
2278
+ if (!defined("PHP_EOL")) define("PHP_EOL", "\r\n");
2279
+
2280
+ ////////////////////////////////////////////////////////////////////////////////////////
 
 
 
 
 
 
 
2281
 
2282
 
2283
 
2284
  /**
2285
+ * Includes
2286
+ *
2287
+ * @since 1.0
2288
+ */
2289
+ if ( is_admin() && !QtranslateSlug::block_activate() ) // setting options page
2290
+ include_once('qtranslate-slug-settings.php');
2291
+
2292
+ include_once('termmeta-core.php'); // termmeta install and core functions
2293
+
2294
+ ////////////////////////////////////////////////////////////////////////////////////////
2295
+
 
 
 
 
 
 
2296
 
 
 
 
 
2297
 
2298
+ /**
2299
+ * Init the plugin
2300
+ *
2301
+ * @since 1.0
2302
+ */
2303
+ global $qtranslate_slug;
2304
+
2305
+ $qtranslate_slug = new QtranslateSlug();
2306
+
2307
+ // plugin activation
2308
+ register_activation_hook( __FILE__, array($qtranslate_slug, 'install') );
2309
+
2310
+ // plugin deactivation
2311
+ register_deactivation_hook( __FILE__, array($qtranslate_slug, 'deactivate') );
2312
+
2313
+ // plugin uninstall
2314
+ register_uninstall_hook( __FILE__, 'qts_uninstall' );
2315
+
2316
+ // plugin init
2317
+ add_action('plugins_loaded', array($qtranslate_slug, 'init') );
2318
+
2319
+ ////////////////////////////////////////////////////////////////////////////////////////
2320
+
2321
+
2322
+
2323
+ /**
2324
+ * Language Selector Code for templating
2325
+ *
2326
+ * @since 1.0
2327
+ */
2328
+ function qts_language_menu($type = "text", $args = array()) {
2329
+ global $qtranslate_slug;
2330
 
2331
+ $qtranslate_slug->language_menu($type, $args);
 
 
 
 
2332
  }
2333
 
2334
 
2335
+
2336
+ /**
2337
+ * Add a "Settings" link to the plugins.php page for Qtranslate Slug
2338
+ *
2339
+ * @package Qtranslate Slug
2340
+ * @subpackage Settings
2341
+ * @version 1.0
2342
+ *
2343
+ * @return calls qts_show_msg()
2344
+ */
2345
+ function qts_add_settings_link( $links, $file ) {
2346
 
2347
+ if (QtranslateSlug::block_activate()) return $links;
2348
+
2349
+ $this_plugin = plugin_basename( __FILE__ );
2350
+ if( $file == $this_plugin ) {
2351
+ $settings_link = "<a href=\"options-general.php?page=" . QTS_PAGE_BASENAME . "\">" . __( 'Settings' ) . '</a>';
2352
+ array_unshift($links, $settings_link);
2353
  }
2354
+ return $links;
2355
  }
2356
+ add_filter( 'plugin_action_links', 'qts_add_settings_link', 10, 2 );
2357
 
 
2358
 
2359
 
2360
+ /**
2361
+ * Delete plugin stored data ( options, termmeta table and postmeta data ) ################################################ test this function
2362
+ *
2363
+ * @package Qtranslate Slug
2364
+ * @subpackage Settings
2365
+ * @version 1.0
2366
+ *
2367
+ */
2368
+ function qts_uninstall() {
2369
+ global $q_config, $wpdb;
2370
+
2371
+ // options
2372
+ delete_option(QTS_OPTIONS_NAME);
2373
+ delete_option('qts_version');
2374
+
2375
+ // delete termmeta table
2376
+ $wpdb->query("DROP TABLE IF EXISTS $wpdb->termmeta");
2377
+
2378
+ // delete postmeta data
2379
+ $meta_keys = array();
2380
+ foreach ($q_config['enabled_languages'] as $lang) $meta_keys[] = sprintf("_qts_slug_%s", $lang);
2381
+ $meta_keys = "'". implode( "','", $meta_keys ) . "'";
2382
+ $wpdb->query("DELETE from $wpdb->postmeta WHERE meta_key IN ($meta_keys)");
2383
+ }
readme.txt DELETED
@@ -1,83 +0,0 @@
1
- === Qtranslate Slug ===
2
- Contributors: Carlos Sanz García
3
- Donate link: none
4
- Tags: qtranslate, slug, multilanguage
5
- Requires at least: 3.0
6
- Tested up to: 3.3.2
7
- Version: 0.9
8
- License: GPLv2 or later
9
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
-
11
- Allows to define a slug for each language and some qTranslate bug fixes
12
-
13
- == Description ==
14
-
15
- This plugin allows translated slugs in Qtranslate.
16
- You need install and activate previously Qtranslate, if not, Qtranslate Slug will not work.
17
-
18
- Tested with Qtranslate versions 2.5.8 and 2.5.9
19
-
20
- == Installation ==
21
-
22
- This plugins requires qTranslate installed previously, if not, it will not activate.
23
-
24
- 1. Upload `qtranslate-slug` to the `/wp-content/plugins/` directory
25
- 1. Activate the plugin through the 'Plugins' menu in WordPress
26
- 1. That's all!
27
-
28
- == Frequently Asked Questions ==
29
-
30
- = It works with posts and pages, but with other content type ? =
31
-
32
- This plugin allows to translate slugs of: posts, pages, custom post types, categories, tags and custom taxonomies.
33
-
34
- = How can I insert a language selector in my theme ? =
35
-
36
- Place `<?php if (function_exists('qTranslateSlug_generateLanguageSelectCode') ) qTranslateSlug_generateLanguageSelectCode('text'); ?>` in your template.
37
-
38
- == Screenshots ==
39
-
40
- 1. This screen shot description corresponds to screenshot-1.(png|jpg|jpeg|gif). Note that the screenshot is taken from
41
- the directory of the stable readme.txt, so in this case, `/tags/4.3/screenshot-1.png` (or jpg, jpeg, gif)
42
- 2. This is the second screen shot
43
-
44
- == Changelog ==
45
-
46
- = 0.9 =
47
- * some wordpress qTranslate bug fixes
48
- * adds a javascript solution for qTranslate Nav Menus
49
-
50
- = 0.8 =
51
- * added support por Categories
52
- * added support por Tags
53
- * added support por Taxonomies
54
- * added support por Custom Post Types
55
-
56
- = 0.7 ( enhanced by Zapo (http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499) ) =
57
- * added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit
58
-
59
- = 0.5 and 0.6 enhanched by Marco Del Percio =
60
-
61
- == Upgrade Notice ==
62
-
63
- = 0.9 =
64
- This version fix some bugs and allow multilanguage in nav-menus.
65
-
66
- = 0.8 =
67
- A lot of slugs content allowed
68
-
69
- = 0.7 =
70
- This version allows TLD domain option for a different Qtranslate fork maded by Zappo
71
-
72
-
73
- == Todo ==
74
-
75
- * admin options page for setup the taxonomies names
76
- * change the database system ( post meta ), without installing tables
77
- * generate translated slug automatically from the translated title
78
- * check if the slug is already used, and add a progressive number in this case
79
- * force the use of the translated slug if defined
80
- * force to show a page/post only at the correct URL
81
- * try to redirect from a wrong URL to a correct URL
82
- * keep track of renamed slugs, redirecting from old to new slugs
83
- * translate categories and tags slugs.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
screenshot-1.png ADDED
Binary file
screenshot-2.png ADDED
Binary file
screenshot-3.png ADDED
Binary file
screenshot-4.png ADDED
Binary file
termmeta-core.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Install Term meta table - setup table, store db version for future updates
4
+ */
5
+ function install_term_meta_table() {
6
+ global $wpdb;
7
+
8
+ $collate = '';
9
+ if($wpdb->supports_collation()) {
10
+ if(!empty($wpdb->charset)) $collate = "DEFAULT CHARACTER SET $wpdb->charset";
11
+ if(!empty($wpdb->collate)) $collate .= " COLLATE $wpdb->collate";
12
+ }
13
+
14
+ $sql = "CREATE TABLE IF NOT EXISTS ". $wpdb->prefix . "termmeta" ." (
15
+ `meta_id` bigint(20) NOT NULL AUTO_INCREMENT,
16
+ `term_id` bigint(20) NOT NULL DEFAULT '0',
17
+ `meta_key` varchar(255) NULL,
18
+ `meta_value` longtext NULL,
19
+ PRIMARY KEY id (`meta_id`)) $collate;";
20
+ $wpdb->query($sql);
21
+ }
22
+
23
+
24
+
25
+ function simple_post_meta_define_table() {
26
+ global $wpdb;
27
+ $wpdb->termmeta = $wpdb->prefix . 'termmeta';
28
+ }
29
+ add_action( 'init', 'simple_post_meta_define_table' );
30
+
31
+ /**
32
+ * Updates metadata cache for list of term IDs.
33
+ *
34
+ * Performs SQL query to retrieve the metadata for the term IDs and updates the
35
+ * metadata cache for the terms. Therefore, the functions, which call this
36
+ * function, do not need to perform SQL queries on their own.
37
+ *
38
+ * @param array $term_ids List of post IDs.
39
+ * @return bool|array Returns false if there is nothing to update or an array of metadata.
40
+ */
41
+ function update_termmeta_cache($term_ids) {
42
+ return update_meta_cache('term', $term_ids);
43
+ }
44
+
45
+
46
+
47
+ /**
48
+ * Add meta data field to a term.
49
+ *
50
+ * @param int $term_id Term ID.
51
+ * @param string $key Metadata name.
52
+ * @param mixed $value Metadata value.
53
+ * @param bool $unique Optional, default is false. Whether the same key should not be added.
54
+ * @return bool False for failure. True for success.
55
+ */
56
+ function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {
57
+ return add_metadata('term', $term_id, $meta_key, $meta_value, $unique);
58
+ }
59
+
60
+
61
+
62
+ /**
63
+ * Remove metadata matching criteria from a term.
64
+ *
65
+ * You can match based on the key, or key and value. Removing based on key and
66
+ * value, will keep from removing duplicate metadata with the same key. It also
67
+ * allows removing all metadata matching key, if needed.
68
+ *
69
+ * @param int $term_id Term ID
70
+ * @param string $meta_key Metadata name.
71
+ * @param mixed $meta_value Optional. Metadata value.
72
+ * @return bool False for failure. True for success.
73
+ */
74
+ function delete_term_meta( $term_id, $meta_key, $meta_value = '' ) {
75
+ return delete_metadata('term', $term_id, $meta_key, $meta_value);
76
+ }
77
+
78
+
79
+
80
+ /**
81
+ * Retrieve term meta field for a term.
82
+ *
83
+ * @param int $term_id Term ID.
84
+ * @param string $key The meta key to retrieve.
85
+ * @param bool $single Whether to return a single value.
86
+ * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
87
+ * is true.
88
+ */
89
+ function get_term_meta( $term_id, $key, $single = false ) {
90
+ return get_metadata('term', $term_id, $key, $single);
91
+ }
92
+
93
+
94
+
95
+ /**
96
+ * Update term meta field based on term ID.
97
+ *
98
+ * Use the $prev_value parameter to differentiate between meta fields with the
99
+ * same key and term ID.
100
+ *
101
+ * If the meta field for the term does not exist, it will be added.
102
+ *
103
+ * @param int $term_id Term ID.
104
+ * @param string $key Metadata key.
105
+ * @param mixed $value Metadata value.
106
+ * @param mixed $prev_value Optional. Previous value to check before removing.
107
+ * @return bool False on failure, true if success.
108
+ */
109
+ function update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {
110
+
111
+ return update_metadata('term', $term_id, $meta_key, $meta_value, $prev_value);
112
+ }
113
+
114
+
115
+
116
+ /**
117
+ * Delete everything from term meta matching meta key.
118
+ *
119
+ * @param string $term_meta_key Key to search for when deleting.
120
+ * @return bool Whether the term meta key was deleted from the database
121
+ */
122
+ function delete_term_meta_by_key($term_meta_key) {
123
+ if ( !$term_meta_key )
124
+ return false;
125
+
126
+ global $wpdb;
127
+ $term_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT term_id FROM $wpdb->termmeta WHERE meta_key = %s", $term_meta_key));
128
+ if ( $term_ids ) {
129
+ $termmetaids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->termmeta WHERE meta_key = %s", $term_meta_key ) );
130
+ $in = implode( ',', array_fill(1, count($termmetaids), '%d'));
131
+ do_action( 'delete_termmeta', $termmetaids );
132
+ $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->termmeta WHERE meta_id IN($in)", $termmetaids ));
133
+ do_action( 'deleted_termmeta', $termmetaids );
134
+ foreach ( $term_ids as $term_id )
135
+ wp_cache_delete($term_id, 'term_meta');
136
+ return true;
137
+ }
138
+ return false;
139
+ }
140
+
141
+
142
+
143
+ /**
144
+ * Retrieve term meta fields, based on term ID.
145
+ *
146
+ * The term meta fields are retrieved from the cache, so the function is
147
+ * optimized to be called more than once. It also applies to the functions, that
148
+ * use this function.
149
+ *
150
+ * @param int $term_id term ID
151
+ * @return array
152
+ */
153
+ function get_term_custom( $term_id ) {
154
+ $term_id = (int) $term_id;
155
+
156
+ if ( ! wp_cache_get($term_id, 'term_meta') )
157
+ update_termmeta_cache($term_id);
158
+
159
+ return wp_cache_get($term_id, 'term_meta');
160
+ }
161
+
162
+
163
+
164
+ /**
165
+ * Retrieve meta field names for a term.
166
+ *
167
+ * If there are no meta fields, then nothing (null) will be returned.
168
+ *
169
+ * @param int $term_id term ID
170
+ * @return array|null Either array of the keys, or null if keys could not be retrieved.
171
+ */
172
+ function get_term_custom_keys( $term_id ) {
173
+ $custom = get_term_custom( $term_id );
174
+
175
+ if ( !is_array($custom) )
176
+ return;
177
+
178
+ if ( $keys = array_keys($custom) )
179
+ return $keys;
180
+ }
181
+
182
+
183
+
184
+ /**
185
+ * Retrieve values for a custom term field.
186
+ *
187
+ * The parameters must not be considered optional. All of the term meta fields
188
+ * will be retrieved and only the meta field key values returned.
189
+ *
190
+ * @param string $key Meta field key.
191
+ * @param int $term_id Term ID
192
+ * @return array Meta field values.
193
+ */
194
+ function get_term_custom_values( $key = '', $term_id ) {
195
+ if ( !$key )
196
+ return null;
197
+
198
+ $custom = get_term_custom($term_id);
199
+
200
+ return isset($custom[$key]) ? $custom[$key] : null;
201
+ }
version.txt CHANGED
@@ -1,3 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  = 0.9 =
2
  * some wordpress qTranslate bug fixes
3
  * adds a javascript solution for qTranslate Nav Menus
1
+ = 1.0 =
2
+ * new branch, the plugin has been rewrited: now the code is commented and wrapped inside a class, also all code has change and the performance has been increased.
3
+ * structural changes:
4
+ * no ID for slug type, then don't install qtrasnlate_slug table.
5
+ * slugs now are stored on meta tables, installation creates a termmeta table with some new 'core functions' to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/).
6
+ * some automation:
7
+ * the plugin generates translated slug automatically from title in empty cases (like wordpress).
8
+ * the plugin checks if the slug already exists (per each language and type / taxonomy), and adds a progressive number in this case (like wordpress).
9
+ * works on ajax requests like creatig new taxonomies on edit post page.
10
+ * possibility to translate the base of permastructs for 'post_types' and 'taxonomies' (uses $wp_rewrite).
11
+ * added some filters:
12
+ * 'qts_validate_post_slug' : args( $post (object), $slug (string), $lang (string) ) / filter to process the post slug before is saved on the database.
13
+ * 'qts_validate_term_slug' : args( $term (object), $slug (string), $lang (string) ) / filter to process the term slug before is saved on the database.
14
+ * 'qts_current_url' : args ( $url (string), $lang (string) ) / filter to process the entire url after it has been generated.
15
+ * 'qts_permastruct' : args ( $permastruct (string), $name (string) ) / filter to process the permastruct, used for change the base.
16
+ * added plugin language textdomain (.pot file)
17
+ * new admin options page for save the base permastructs.
18
+ * import process when the plugin updates older versions.
19
+ * some bug fixes.
20
+ * some Qtranslate patches.
21
+
22
  = 0.9 =
23
  * some wordpress qTranslate bug fixes
24
  * adds a javascript solution for qTranslate Nav Menus