1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
/**
|
3 |
|
|
* @file
|
4 |
|
|
* Multilingual content selection module.
|
5 |
|
|
*
|
6 |
|
|
* Alters content queries to add language conditions.
|
7 |
|
|
*
|
8 |
|
|
* Queries tagged with 'i18n_select' or that already have a language condition will not be altered.
|
9 |
|
|
*/
|
10 |
|
|
|
11 |
|
|
// No language selection
|
12 |
|
|
define('I18N_SELECT_NONE', 0);
|
13 |
|
|
// Content with current language and undefined language
|
14 |
|
|
define('I18N_SELECT_NORMAL', 1);
|
15 |
|
|
// Select default language when current language is missing
|
16 |
|
|
define('I18N_SELECT_MISSING', 2);
|
17 |
|
|
|
18 |
|
|
/**
|
19 |
|
|
* Enable on every page except the listed pages.
|
20 |
|
|
*/
|
21 |
|
|
define('I18N_SELECT_PAGE_NOTLISTED', 0);
|
22 |
|
|
/**
|
23 |
|
|
* Enable on only the listed pages.
|
24 |
|
|
*/
|
25 |
|
|
define('I18N_SELECT_PAGE_LISTED', 1);
|
26 |
|
|
/**
|
27 |
|
|
* Enable if the associated PHP code returns TRUE.
|
28 |
|
|
*/
|
29 |
|
|
define('I18N_SELECT_PAGE_PHP', 2);
|
30 |
|
|
|
31 |
|
|
/**
|
32 |
|
|
* Implements hook_init().
|
33 |
|
|
*/
|
34 |
|
|
function i18n_select_init() {
|
35 |
|
|
// Determine selection mode for this page
|
36 |
|
|
i18n_select(i18n_select_page());
|
37 |
|
|
}
|
38 |
|
|
|
39 |
|
|
/**
|
40 |
|
|
* Implements hook_block_list_alter().
|
41 |
|
|
*
|
42 |
|
|
* Dirty trick to enable selection for blocks though it may be disabled for the current page.
|
43 |
|
|
*/
|
44 |
|
|
function i18n_select_block_list_alter(&$blocks) {
|
45 |
|
|
// Still, skip for form submission. There are pages like the ones produced
|
46 |
|
|
// by overlay that render the blocks before the page.
|
47 |
|
|
// See overlay_init(), overlay_overlay_child_initialize()
|
48 |
|
|
if (empty($_POST) && !isset($_GET['token']) && variable_get('i18n_select_page_block', TRUE)) {
|
49 |
|
|
i18n_select(TRUE);
|
50 |
|
|
}
|
51 |
|
|
}
|
52 |
|
|
|
53 |
|
|
/**
|
54 |
|
|
* Implements hook_menu().
|
55 |
|
|
*/
|
56 |
|
|
function i18n_select_menu() {
|
57 |
|
|
$items['admin/config/regional/i18n/select'] = array(
|
58 |
|
|
'title' => 'Selection',
|
59 |
|
|
'description' => 'Configure extended options for multilingual content and translations.',
|
60 |
|
|
'page callback' => 'drupal_get_form',
|
61 |
|
|
'page arguments' => array('i18n_select_admin_settings'),
|
62 |
|
|
'access arguments' => array('administer site configuration'),
|
63 |
|
|
'file' => 'i18n_select.admin.inc',
|
64 |
|
|
'type' => MENU_LOCAL_TASK,
|
65 |
|
|
);
|
66 |
|
|
return $items;
|
67 |
|
|
}
|
68 |
|
|
|
69 |
|
|
/**
|
70 |
|
|
* Get current mode for i18n selection
|
71 |
|
|
*
|
72 |
|
|
* @param $type
|
73 |
|
|
* Selection type: 'nodes', 'taxonomy', etc..
|
74 |
|
|
*/
|
75 |
|
|
function i18n_select_mode($type = NULL) {
|
76 |
|
|
if (i18n_select() && (!$type || variable_get('i18n_select_' . $type, TRUE))) {
|
77 |
|
|
return I18N_SELECT_NORMAL;
|
78 |
|
|
}
|
79 |
|
|
else {
|
80 |
|
|
return I18N_SELECT_NONE;
|
81 |
|
|
}
|
82 |
|
|
}
|
83 |
|
|
|
84 |
|
|
/**
|
85 |
fc3d89c3
|
Assos Assos
|
* Check current path to enable selection.
|
86 |
85ad3d82
|
Assos Assos
|
*
|
87 |
fc3d89c3
|
Assos Assos
|
* This works pretty much like block visibility.
|
88 |
85ad3d82
|
Assos Assos
|
*
|
89 |
fc3d89c3
|
Assos Assos
|
* @return bool
|
90 |
85ad3d82
|
Assos Assos
|
* TRUE if content selection should be enabled for this page.
|
91 |
|
|
*/
|
92 |
|
|
function i18n_select_page() {
|
93 |
|
|
static $mode;
|
94 |
|
|
|
95 |
|
|
if (!isset($mode)) {
|
96 |
|
|
$mode = &drupal_static(__FUNCTION__);
|
97 |
|
|
$visibility = variable_get('i18n_select_page_mode', I18N_SELECT_PAGE_NOTLISTED);
|
98 |
|
|
if ($pages = variable_get('i18n_select_page_list', 'admin/*')) {
|
99 |
|
|
// Convert path to lowercase. This allows comparison of the same path
|
100 |
|
|
// with different case. Ex: /Page, /page, /PAGE.
|
101 |
|
|
$pages = drupal_strtolower($pages);
|
102 |
|
|
if ($visibility < I18N_SELECT_PAGE_PHP) {
|
103 |
fc3d89c3
|
Assos Assos
|
// @see views_ajax()
|
104 |
|
|
// @see I18NSelectAdminViewsAjax::testViewsAjaxWithoutSkippingTags()
|
105 |
|
|
$path = isset($_REQUEST['view_path']) ? $_REQUEST['view_path'] : $_GET['q'];
|
106 |
|
|
// Convert the Drupal path to lowercase.
|
107 |
|
|
$path = drupal_strtolower(drupal_get_path_alias($path));
|
108 |
85ad3d82
|
Assos Assos
|
// Compare the lowercase internal and lowercase path alias (if any).
|
109 |
|
|
$page_match = drupal_match_path($path, $pages);
|
110 |
|
|
if ($path != $_GET['q']) {
|
111 |
|
|
$page_match = $page_match || drupal_match_path($_GET['q'], $pages);
|
112 |
|
|
}
|
113 |
|
|
// When $visibility has a value of 0 (I18N_SELECT_PAGE_NOTLISTED),
|
114 |
|
|
// the block is displayed on all pages except those listed in $pages.
|
115 |
fc3d89c3
|
Assos Assos
|
// When set to 1 (I18N_SELECT_PAGE_LISTED), it is displayed only on
|
116 |
|
|
// those pages listed in $pages.
|
117 |
85ad3d82
|
Assos Assos
|
$mode = !($visibility xor $page_match);
|
118 |
|
|
}
|
119 |
|
|
elseif (module_exists('php')) {
|
120 |
|
|
$mode = php_eval($pages);
|
121 |
|
|
}
|
122 |
|
|
else {
|
123 |
|
|
$mode = FALSE;
|
124 |
|
|
}
|
125 |
|
|
}
|
126 |
|
|
else {
|
127 |
fc3d89c3
|
Assos Assos
|
// No pages defined, still respect the setting (unlike blocks).
|
128 |
85ad3d82
|
Assos Assos
|
$mode = $visibility == I18N_SELECT_PAGE_NOTLISTED;
|
129 |
|
|
}
|
130 |
|
|
}
|
131 |
|
|
|
132 |
|
|
return $mode;
|
133 |
|
|
}
|
134 |
|
|
|
135 |
|
|
/**
|
136 |
|
|
* Implementation of hook_query_node_access_alter().
|
137 |
|
|
*
|
138 |
|
|
* Rewrite node queries so language selection options are enforced.
|
139 |
|
|
*/
|
140 |
|
|
function i18n_select_query_node_access_alter(QueryAlterableInterface $query) {
|
141 |
|
|
if (i18n_select_mode('nodes') && i18n_select_check_query($query, 'nid') &&
|
142 |
|
|
($table_alias = i18n_select_check_table($query, 'node', 'nid'))) {
|
143 |
|
|
$query->condition($table_alias . '.language', i18n_select_langcodes());
|
144 |
|
|
// Mark query as altered
|
145 |
|
|
$query->addTag('i18n_select');
|
146 |
|
|
}
|
147 |
|
|
}
|
148 |
|
|
|
149 |
|
|
/**
|
150 |
|
|
* Implementation of hook_query_term_access_alter().
|
151 |
|
|
*
|
152 |
|
|
* Rewrite taxonomy term queries so language selection options are enforced.
|
153 |
|
|
*/
|
154 |
|
|
function i18n_select_query_term_access_alter(QueryAlterableInterface $query) {
|
155 |
|
|
if (module_exists('i18n_taxonomy') && i18n_select_mode('taxonomy') && i18n_select_check_query($query, 'tid') &&
|
156 |
|
|
($table_alias = i18n_select_check_table($query, 'taxonomy_term_data', 'tid'))) {
|
157 |
|
|
$query->condition($table_alias . '.language', i18n_select_langcodes());
|
158 |
|
|
// Mark query as altered
|
159 |
|
|
$query->addTag('i18n_select');
|
160 |
|
|
}
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
/**
|
164 |
|
|
* Check table exists in query and get alias for it.
|
165 |
|
|
*
|
166 |
|
|
* @param $query
|
167 |
|
|
* Query object
|
168 |
|
|
* @param $table_name
|
169 |
|
|
* Table name to find.
|
170 |
|
|
* @param $field_name
|
171 |
|
|
* field to join the table if needed.
|
172 |
|
|
*
|
173 |
|
|
* @return
|
174 |
|
|
* Table alias if found, none if not.
|
175 |
|
|
*/
|
176 |
|
|
function i18n_select_check_table($query, $table_name, $field_name) {
|
177 |
|
|
$tables = $query->getTables();
|
178 |
|
|
foreach ($tables as $table) {
|
179 |
|
|
if (!($table instanceof SelectQueryInterface) && $table['table'] == $table_name) {
|
180 |
|
|
return _i18n_select_table_alias($table);
|
181 |
|
|
}
|
182 |
|
|
}
|
183 |
|
|
// Join the table if we can find the key field on any of the tables
|
184 |
|
|
// And all the conditions have a table alias (or there's a unique table).
|
185 |
|
|
if (count($tables) == 1) {
|
186 |
|
|
$table = reset($tables);
|
187 |
|
|
$table_alias = _i18n_select_table_alias($table);
|
188 |
|
|
if (i18n_select_check_conditions($query, $table_alias)) {
|
189 |
|
|
$join_table = $table_alias;
|
190 |
|
|
}
|
191 |
|
|
}
|
192 |
|
|
elseif (i18n_select_check_conditions($query)) {
|
193 |
|
|
// Try to find the right field in the table schema.
|
194 |
|
|
foreach ($tables as $table) {
|
195 |
|
|
$schema = drupal_get_schema($table['table']);
|
196 |
|
|
if ($schema && !empty($schema['fields'][$field_name])) {
|
197 |
|
|
$join_table = _i18n_select_table_alias($table);
|
198 |
|
|
break;
|
199 |
|
|
}
|
200 |
|
|
}
|
201 |
|
|
}
|
202 |
|
|
if (!empty($join_table)) {
|
203 |
|
|
return $query->join($table_name, $table_name, $join_table . '.' . $field_name . ' = %alias.' . $field_name);
|
204 |
|
|
}
|
205 |
|
|
else {
|
206 |
|
|
return FALSE;
|
207 |
|
|
}
|
208 |
|
|
}
|
209 |
|
|
|
210 |
|
|
/**
|
211 |
|
|
* Get table alias
|
212 |
|
|
*/
|
213 |
|
|
function _i18n_select_table_alias($table) {
|
214 |
|
|
return !empty($table['alias']) ? $table['alias'] : $table['table'];
|
215 |
|
|
}
|
216 |
|
|
|
217 |
|
|
/**
|
218 |
|
|
* Check all query conditions have a table alias.
|
219 |
|
|
*
|
220 |
|
|
* @param $table_alias
|
221 |
|
|
* Optional table alias for fields without table.
|
222 |
|
|
*
|
223 |
|
|
* @return boolean
|
224 |
|
|
* TRUE if table conditions are ok, FALSE otherwise.
|
225 |
|
|
*/
|
226 |
|
|
function i18n_select_check_conditions($query, $table_alias = NULL) {
|
227 |
|
|
$conditions =& $query->conditions();
|
228 |
|
|
foreach ($conditions as $index => $condition) {
|
229 |
e4c061ad
|
Assos Assos
|
if (is_array($condition) && !empty($condition['field'])) {
|
230 |
85ad3d82
|
Assos Assos
|
if (strpos($condition['field'], '.') === FALSE) {
|
231 |
|
|
if ($table_alias) {
|
232 |
|
|
// Change the condition to include a table alias.
|
233 |
|
|
$conditions[$index]['field'] = $table_alias . '.' . $condition['field'];
|
234 |
|
|
}
|
235 |
|
|
else {
|
236 |
|
|
// We won't risk joining anything here.
|
237 |
|
|
return FALSE;
|
238 |
|
|
}
|
239 |
|
|
}
|
240 |
|
|
}
|
241 |
|
|
}
|
242 |
|
|
return TRUE;
|
243 |
|
|
}
|
244 |
|
|
|
245 |
|
|
/**
|
246 |
|
|
* Check whether we should apply language conditions here:
|
247 |
|
|
* - The query has not been tagged with 'i18n_select'
|
248 |
|
|
* - The query doesn't have already a language condition
|
249 |
|
|
* - All the conditions have a table alias or there's only one table.
|
250 |
|
|
* - We are not loading specific objects (no condition for index field).
|
251 |
|
|
*
|
252 |
|
|
* @param $query
|
253 |
|
|
* Query object.
|
254 |
|
|
* @param $index_field
|
255 |
|
|
* Object index field to check we don't have 'IN' conditions for it.
|
256 |
|
|
*/
|
257 |
|
|
function i18n_select_check_query($query, $index_field = NULL) {
|
258 |
|
|
static $tags;
|
259 |
|
|
// Skip queries with certain tags
|
260 |
|
|
if (!isset($tags)) {
|
261 |
|
|
$tags = ($skip = variable_get('i18n_select_skip_tags', 'views')) ? array_map('trim', explode(',', $skip)) : array();
|
262 |
|
|
$tags[] = 'i18n_select';
|
263 |
|
|
}
|
264 |
|
|
foreach ($tags as $tag) {
|
265 |
|
|
if ($query->hasTag($tag)) {
|
266 |
|
|
return FALSE;
|
267 |
|
|
}
|
268 |
|
|
}
|
269 |
|
|
// Check all the conditions to see whether the query is suitable for altering.
|
270 |
|
|
foreach ($query->conditions() as $condition) {
|
271 |
|
|
if (is_array($condition)) {
|
272 |
|
|
// @todo For some complex queries, like search ones, field is a DatabaseCondition object
|
273 |
|
|
if (!isset($condition['field']) || !is_string($condition['field'])) {
|
274 |
|
|
// There's a weird condition field, we won't take any chances.
|
275 |
|
|
return FALSE;
|
276 |
|
|
}
|
277 |
|
|
else {
|
278 |
|
|
// Just check the condition doesn't include the language field
|
279 |
|
|
if (strpos($condition['field'], '.') === FALSE) {
|
280 |
|
|
$field = $condition['field'];
|
281 |
|
|
}
|
282 |
|
|
else {
|
283 |
|
|
list($table, $field) = explode('.', $condition['field']);
|
284 |
|
|
}
|
285 |
|
|
if ($field == 'language') {
|
286 |
|
|
return FALSE;
|
287 |
|
|
}
|
288 |
|
|
// Check 'IN' conditions for index field, usually entity loading for specific objects.
|
289 |
|
|
if ($field == $index_field && $condition['operator'] == 'IN') {
|
290 |
|
|
return FALSE;
|
291 |
|
|
}
|
292 |
|
|
}
|
293 |
|
|
}
|
294 |
|
|
}
|
295 |
|
|
// If the language field is present we don't want to do any filtering.
|
296 |
|
|
$fields = $query->getFields();
|
297 |
|
|
if (isset($fields['language'])) {
|
298 |
|
|
return FALSE;
|
299 |
|
|
}
|
300 |
|
|
|
301 |
|
|
return TRUE;
|
302 |
|
|
}
|
303 |
|
|
|
304 |
|
|
/**
|
305 |
|
|
* Get main language for content selection
|
306 |
|
|
*/
|
307 |
|
|
function i18n_select_language() {
|
308 |
|
|
return $GLOBALS[LANGUAGE_TYPE_CONTENT];
|
309 |
|
|
}
|
310 |
|
|
|
311 |
|
|
/**
|
312 |
|
|
* Get language codes for content selection to use in query conditions
|
313 |
|
|
*/
|
314 |
|
|
function i18n_select_langcodes() {
|
315 |
|
|
return array(i18n_select_language()->language, LANGUAGE_NONE);
|
316 |
|
|
}
|