/[drupal]/contributions/modules/context/context_prefix/context_prefix.module
ViewVC logotype

Contents of /contributions/modules/context/context_prefix/context_prefix.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations) (download) (as text)
Mon Oct 6 21:49:29 2008 UTC (13 months, 2 weeks ago) by yhahn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +331 -96 lines
File MIME type: text/x-php
Merging pair prefixing from DRUPAL-5 branch
1 <?php
2 // $Id: context_prefix.module,v 1.5 2008/08/18 11:42:08 yhahn Exp $
3
4 define('CONTEXT_PREFIX_PATH', 0);
5 define('CONTEXT_PREFIX_SUBDOMAIN', 1);
6 define('CONTEXT_PREFIX_DOMAIN', 2);
7 define('CONTEXT_PREFIX_PAIR', 3);
8
9 /**
10 * Implementation of hook_theme().
11 */
12 function context_prefix_theme($existing, $type, $theme, $path) {
13 return array(
14 'context_prefix_settings_form' => array(
15 'arguments' => array('form' => NULL),
16 ),
17 'context_links' => array(
18 'arguments' => array('links' => NULL, 'attributes' => array('class' => 'links')),
19 ),
20 );
21 }
22
23 /**
24 * Implementation of hook_menu().
25 */
26 function context_prefix_menu() {
27 $items = array();
28 $items['admin/build/context/prefix'] = array(
29 'type' => module_exists('context_ui') ? MENU_LOCAL_TASK : MENU_NORMAL_ITEM,
30 'title' => t('Context prefix'),
31 'description' => t('Settings for context prefix.'),
32 'page callback' => 'drupal_get_form',
33 'page arguments' => array('context_prefix_settings_form'),
34 'access callback' => 'user_access',
35 'access argumnets' => array('administer site configuration'),
36 'weight' => 10,
37 );
38 $items['admin/build/context/prefix/settings'] = array(
39 'type' => MENU_DEFAULT_LOCAL_TASK,
40 'title' => t('Settings'),
41 'page callback' => 'drupal_get_form',
42 'page arguments' => array('context_prefix_settings_form'),
43 'access callback' => 'user_access',
44 'access arguments' => array('administer site configuration'),
45 'weight' => 0,
46 );
47 $items['admin/build/context/prefix/list'] = array(
48 'type' => MENU_LOCAL_TASK,
49 'title' => t('Registered prefixes'),
50 'page callback' => 'context_prefix_admin',
51 'access callback' => 'user_access',
52 'access arguments' => array('administer site configuration'),
53 'weight' => 10,
54 );
55 return $items;
56 }
57
58 /**
59 * Implementation of hook_init()
60 * Checks for any valid context prefixes in request string and sets the context appropriately
61 */
62 function context_prefix_init() {
63 static $once;
64 if (!$once) {
65 _context_prefix_init(CONTEXT_PREFIX_PATH);
66 _context_prefix_init(CONTEXT_PREFIX_DOMAIN);
67 _context_prefix_init(CONTEXT_PREFIX_PAIR);
68 $once = true;
69 }
70 }
71
72 /**
73 * Helper function to initialize, parse + set prefixed contexts.
74 */
75 function _context_prefix_init($method = CONTEXT_PREFIX_PATH) {
76 switch ($method) {
77 case CONTEXT_PREFIX_PATH:
78 $q = isset($_REQUEST["q"]) ? trim($_REQUEST["q"], "/") : '';
79 $parsed = context_prefix_parse(CONTEXT_PREFIX_PATH, $q);
80 break;
81 case CONTEXT_PREFIX_PAIR:
82 $q = isset($_REQUEST["q"]) ? trim($_REQUEST["q"], "/") : '';
83 $parsed = context_prefix_parse(CONTEXT_PREFIX_PAIR, $q);
84 break;
85 case CONTEXT_PREFIX_DOMAIN:
86 $host = $_SERVER['HTTP_HOST'];
87 // We handle sub.domain.com, and nothing more (no sub1.sub2.domain.com).
88 $q = str_replace('http://','',$host);
89 $parsed = context_prefix_parse(CONTEXT_PREFIX_DOMAIN, $q);
90 break;
91 }
92
93 // if $_GET and $_REQUEST are different, the path has NOT been
94 // aliased. We may need to rewrite the path.
95 if (in_array($method, array(CONTEXT_PREFIX_PATH, CONTEXT_PREFIX_PAIR)) && ($_GET['q'] == $_REQUEST['q'])) {
96 $q = context_prefix_unprefix($q, $method);
97 // there is nothing beyond the path prefix -- treat as frontpage
98 if ($q == '') {
99 $_GET['q'] = variable_get('site_frontpage', 'node');
100 }
101 // pass the rest of the path onto Drupal cleanly
102 else {
103 $_REQUEST['q'] = $_GET['q'] = _context_prefix_get_normal_path($q);
104 }
105 }
106
107 if (is_array($parsed)) {
108 foreach ($parsed as $prefix => $info) {
109 context_prefix_set($method, $prefix, $info);
110 }
111 }
112 }
113
114 /**
115 * Jose's very smart collision avoidance
116 */
117 if (!function_exists('custom_url_rewrite_outbound')) {
118 function custom_url_rewrite_outbound(&$path, &$options, $original) {
119 return context_prefix_url_rewrite($path, $options, $original);
120 }
121 }
122
123 /**
124 * Rewrites path with current context and removes context if searching for source path
125 */
126 function context_prefix_url_rewrite(&$path, &$options, $original) {
127 $working_path = $path; // preserve original path
128 $args = array();
129
130 // Check to see whether url rewriting has been disabled for this one
131 // instance -- currently only possible through cl()
132 if (!clswitch('get')) {
133 // Retrieve the path prefixes for the current page that were
134 // "stripped out" and write them back into url paths.
135 foreach (context_prefix_get(CONTEXT_PREFIX_PAIR) as $item) {
136 $active_path_prefixes[] = $item['prefix'] .'/'. $item['id'];
137 }
138
139 foreach (context_prefix_get(CONTEXT_PREFIX_PATH) as $item) {
140 $active_path_prefixes[] = $item['prefix'];
141 }
142
143 if (count($active_path_prefixes)) {
144 $parsed = context_prefix_parse(CONTEXT_PREFIX_PATH, $working_path) + context_prefix_parse(CONTEXT_PREFIX_PAIR, $working_path);
145 // A "normal" url was requested -- prefix the path
146 if (!$options['alias'] && !strpos($path, '://') && !count($parsed) && count($active_path_prefixes)) {
147 $args = $args + $active_path_prefixes;
148 }
149 }
150 }
151
152 if ($working_path) {
153 $args[] = $working_path;
154 }
155
156 $path = is_array($args) ? implode('/', $args) : '';
157 }
158
159 /**
160 * Queries the database & modules for valid prefixes based on prefixing method.
161 *
162 * Modules that wish to provide in-code prefixes should implement the
163 * hook_context_prefix_prefixes(). Which should return an array of prefixes by
164 * by provider.
165 *
166 * For example:
167 *
168 * return array(
169 * 'my_module => array(
170 * array('prefix' => 'foo', 'id' => 1),
171 * array('prefix' => 'bar', 'id' => 2),
172 * ),
173 * );
174 */
175 function context_prefix_prefixes($requested_method = CONTEXT_PREFIX_PATH, $reset = FALSE) {
176 static $prefixes;
177 if (!isset($prefixes) || $reset) {
178 $prefixes = array();
179
180 // Invoke context_prefix_prefixes() and gather all prefixes
181 // provided "in code" (or stored by their respective modules)
182 foreach (module_invoke_all('context_prefix_prefixes') as $provider => $items) {
183 $method = variable_get('context_prefix_method_'. $provider, CONTEXT_PREFIX_PATH);
184
185 // If using a prefix pair we don't need to cache the valid prefixes.
186 if ($method == CONTEXT_PREFIX_PAIR) {
187 $prefix = variable_get('context_prefix_method_'. $provider .'_key', false);
188 if ($prefix != false) {
189 $prefixes[$method][$prefix] = array(
190 'provider' => $provider,
191 'id' => null,
192 );
193 }
194 }
195 else {
196 foreach ($items as $item) {
197 if ($item['prefix'] && $item['id']) {
198 $prefixes[$method][$item['prefix']] = array(
199 'provider' => $provider,
200 'id' => $item['id'],
201 );
202 }
203 }
204 }
205 }
206
207 // Gather database prefixes.
208 $result = db_query("SELECT DISTINCT(provider) FROM {context_prefix}");
209 while ($item = db_fetch_object($result)) {
210 $method = variable_get('context_prefix_method_'. $item->provider, CONTEXT_PREFIX_PATH);
211 // Don't load all data base prefixes for keyed pairs.
212 if ($method == CONTEXT_PREFIX_PAIR) {
213 $prefix = variable_get('context_prefix_method_'. $item->provider .'_key', false);
214 if ($prefix != false) {
215 $prefixes[$method][$prefix] = array(
216 'provider' => $item->provider,
217 'id' => null,
218 );
219 }
220 }
221 else {
222 $result2 = db_query("SELECT * FROM {context_prefix} WHERE provider = '%s'", $item->provider);
223 while ($row = db_fetch_object($result2)) {
224 $prefixes[$method][$row->prefix] = array(
225 'provider' => $row->provider,
226 'id' => $row->id,
227 );
228 }
229 }
230 }
231 }
232
233 return (isset($prefixes[$requested_method]) ? $prefixes[$requested_method] : array());
234 }
235
236 /**
237 * Parses a query string of various types (url, domain, etc.) and
238 * returns an array of any found prefixes and their respective
239 * providers/id values.
240 */
241 function context_prefix_parse($method = CONTEXT_PREFIX_PATH, $q) {
242 static $cache;
243 if (!isset($cache[$method][$q])) {
244 $valid_prefixes = context_prefix_prefixes($method);
245 // Parse the provided query string and provide an array of any prefixes found
246 switch ($method) {
247 case CONTEXT_PREFIX_PATH:
248 case CONTEXT_PREFIX_PAIR:
249 $parsed = array();
250 $args = explode('/', $q);
251 $arg = $args[0];
252 while (isset($valid_prefixes[$arg])) {
253 $parsed[$arg] = $valid_prefixes[$arg];
254 array_shift($args);
255 if ($method == CONTEXT_PREFIX_PAIR) {
256 $parsed[$arg]['id'] = array_shift($args);
257 }
258
259 $arg = $args[0];
260 if (in_array($arg, $parsed)) {
261 break;
262 }
263 }
264 $cache[$method][$q] = $parsed;
265 break;
266 case CONTEXT_PREFIX_DOMAIN:
267 $parsed = array();
268 if (isset($valid_prefixes[$q])) {
269 $parsed[$q] = $valid_prefixes[$q];
270 }
271 $cache[$method][$q] = $parsed;
272 break;
273 }
274 }
275 return $cache[$method][$q];
276 }
277
278 /**
279 * Removes any prefixes from a query string. For path prefixes only.
280 */
281 function context_prefix_unprefix($q, $method, $providers = array()) {
282 $parsed = context_prefix_parse($method, $q);
283 if (is_array($providers) && count($providers)) {
284 foreach ($parsed as $prefix => $info) {
285 if (!in_array($info['provider'], $providers)) {
286 unset($parsed[$prefix]);
287 }
288 }
289 }
290 $parsed = array_keys($parsed);
291 $args = explode('/', $q);
292 switch ($method) {
293 case CONTEXT_PREFIX_PATH:
294 $args = array_diff($args, $parsed);
295 break;
296 case CONTEXT_PREFIX_PAIR:
297 foreach ($parsed as $v) {
298 array_splice($args, array_search($v, $args), 2);
299 }
300 break;
301 }
302 return implode('/', $args);
303 }
304
305 /**
306 * Invokes hook_context_prefix_provider() to gather all providers.
307 *
308 * Modules that implement hook_context_prefix_provider need to return an
309 * array of prefix definitions. Each definition should have the following
310 * keys:
311 * - name
312 * - description
313 * - callback
314 * - example
315 *
316 * See the spaces module for an usage example.
317 */
318 function context_prefix_providers($by_method = FALSE) {
319 static $providers;
320 if (!is_array($providers)) {
321 $providers = array();
322 $providers = module_invoke_all('context_prefix_provider');
323 }
324 if ($by_method) {
325 static $methods;
326 if (!isset($methods)) {
327 $methods = new context_prefix_cache();
328
329 foreach ($providers AS $id => $provider) {
330 $methods->add(variable_get('context_prefix_method_'. $id, CONTEXT_PREFIX_PATH), array($id => $provider));
331 }
332 }
333 return $methods->get();
334 }
335 else {
336 return $providers;
337 }
338 }
339
340 /**
341 * Taken from i18n
342 */
343 function _context_prefix_get_normal_path($path) {
344 // If bootstrap, drupal_lookup_path is not defined
345 if (!function_exists('drupal_get_headers')) {
346 return $path;
347 }
348 // Check alias without lang
349 elseif ($alias = drupal_lookup_path('source', $path)) {
350 return $alias;
351 }
352 else {
353 return $path;
354 }
355 }
356
357 /**
358 * Static cache function for setting + storing any prefixed contexts
359 * that are present on this page's request.
360 */
361 function _context_prefix_set($op = 'set', $type = CONTEXT_PREFIX_PATH, $prefix = '', $info = array()) {
362 static $used;
363 if (!$used) {
364 $used = new context_prefix_cache();
365 }
366 switch ($op) {
367 case 'set':
368 // Store prefix for url rewriting later on in the stack
369 $info['prefix'] = $prefix;
370 $used->add($type, $info, false);
371
372 // Fire the provider callback
373 if ($info['provider'] && $info['id']) {
374 // Fire the provider callback
375 $providers = context_prefix_providers();
376 $callback = $providers[$info['provider']]['callback'];
377 $args = isset($providers[$info['provider']]['callback arguments']) ? $providers[$info['provider']]['callback arguments'] : array();
378 $args[] = $info['id'];
379 if (function_exists($callback)) {
380 call_user_func_array($callback, $args);
381 }
382 }
383 break;
384 case 'get':
385 if ($type === 'all') {
386 return $used->get();
387 }
388 else {
389 return $used->get($type);
390 }
391 }
392 }
393
394 /**
395 * Set wrapper for _context_prefix_set()
396 */
397 function context_prefix_set($type = CONTEXT_PREFIX_PATH, $prefix = '', $info = array()) {
398 return _context_prefix_set('set', $type, $prefix, $info);
399 }
400
401 /**
402 * Get wrapper for _context_prefix_set()
403 */
404 function context_prefix_get($type = CONTEXT_PREFIX_PATH) {
405 return _context_prefix_set('get', $type);
406 }
407
408 /**
409 * PAGE CALLBACKS =====================================================
410 */
411
412 /**
413 * Page callback for the context_prefix administration page.
414 */
415 function context_prefix_admin() {
416 global $pager_page_array, $pager_total, $pager_total_items;
417 $page = isset($_GET['page']) ? $_GET['page'] : 0;
418 $element = 0;
419 $limit = 20;
420
421 // Convert $page to an array, used by other functions.
422 $pager_page_array = array($page);
423
424 $methods = _context_ui_options();
425
426 $merged = array();
427 foreach(array_keys($methods) as $method) {
428 foreach(context_prefix_prefixes($method) as $prefix => $info) {
429 $info['prefix'] = $prefix;
430 $merged[] = $info;
431 }
432 }
433 $rows =array();
434 for ($i = $page * $limit; $i < ($page+1) * $limit && $i < count($merged); $i++) {
435 $rows[] = array(
436 $merged[$i]['provider'],
437 $merged[$i]['prefix'],
438 $merged[$i]['id'],
439 $methods[variable_get('context_prefix_method_'. $merged[$i]['provider'], CONTEXT_PREFIX_PATH)],
440 );
441 }
442
443 // We calculate the total of pages as ceil(items / limit).
444 $pager_total_items[$element] = count($merged);
445 $pager_total[$element] = ceil($pager_total_items[$element] / $limit);
446 $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1));
447
448 if ($rows) {
449 $output .= theme('table', array(t('Provider'), t('Prefix'), t('ID'), t('Method')), $rows);
450 $output .= theme('pager');
451 }
452 else {
453 $output .= "<p>". t('No context prefixes have been registered.') ."</p>";
454 }
455 return $output;
456 }
457
458 /**
459 * Settings form for choosing the operating mode of context_prefix
460 */
461 function context_prefix_settings_form() {
462 global $base_url;
463 $form = array();
464
465 $options = _context_ui_options();
466
467 foreach (context_prefix_providers() as $id => $provider) {
468 // Check to see whether provider has limited the available prefixing methods
469 if (is_array($provider['methods']) && count($provider['methods'])) {
470 $provider_options = array();
471 foreach ($provider['methods'] as $method) {
472 $provider_options[$method] = $options[$method];
473 }
474 }
475 else {
476 $provider_options = $options;
477 }
478
479 $form[$id] = array(
480 '#fieldset' => true,
481 '#provider' => true,
482 '#title' => $provider['name'],
483 '#description' => $provider['description'],
484 );
485 $form[$id]['context_prefix_method_'. $id] = array(
486 '#title' => t('Method'),
487 '#type' => 'select',
488 '#options' => $provider_options,
489 '#default_value' => variable_get('context_prefix_method_'. $id, CONTEXT_PREFIX_PATH),
490 );
491 $form[$id]['context_prefix_method_'. $id .'_key'] = array(
492 '#title' => t('Key'),
493 '#type' => 'textfield',
494 '#size' => 12,
495 '#default_value' => variable_get('context_prefix_method_'. $id .'_key', ''),
496 );
497
498 }
499
500 $form['context_prefix_location'] = array(
501 '#type' => 'fieldset',
502 '#title' => t('Prefix location settings'),
503 );
504 $form['context_prefix_location']['context_prefix_base_domain'] = array(
505 '#type' => 'textfield',
506 '#title' => t('Select base domain'),
507 '#description' => t('This setting determines the base domain for domain based context prefixing.'),
508 '#required' => FALSE,
509 '#default_value' => variable_get('context_prefix_base_domain', $base_url),
510 );
511 $form = system_settings_form($form);
512 $form['#theme'] = 'context_prefix_settings_form';
513 return $form;
514 }
515
516 /**
517 * Theme function for context_prefix_settings_form()
518 */
519 function theme_context_prefix_settings_form($form) {
520 $output = '';
521 $rows = array();
522 foreach (element_children($form) as $id) {
523 $row = array();
524 if (isset($form[$id]['#provider'])) {
525 $name = $form[$id]['#title'];
526 $description = $form[$id]['#description'];
527 unset($form[$id]['#title']);
528 unset($form[$id]['#description']);
529 $row[] = "<strong>$name</strong><div class='description'>$description</div>";
530
531 foreach (element_children($form[$id]) as $item) {
532 unset($form[$id][$item]['#title']);
533 $row[] = drupal_render($form[$id][$item]);
534 }
535 }
536 $rows[] = $row;
537 }
538 $output .= theme('table', array(t('Provider'), t('Prefix method'), t('Key')), $rows);
539 $output .= drupal_render($form);
540 drupal_add_js(drupal_get_path("module", "context_prefix") ."/context_prefix_admin.js");
541 return $output;
542 }
543
544 /**
545 * API Functions ======================================================
546 */
547
548 /**
549 * Provides a simple API for validating, adding, and deleting context defintions.
550 */
551 function context_prefix_api($op = 'insert', $context) {
552 switch ($op) {
553 case 'load':
554 if (isset($context['provider'])) {
555 if ($context['id']) {
556 $context = db_fetch_array(db_query("SELECT * FROM {context_prefix} WHERE id = '%s' AND provider = '%s'", $context['id'], $context['provider']));
557 if ($context) {
558 return $context;
559 }
560 }
561 else if ($context['prefix']) {
562 $context = db_fetch_array(db_query("SELECT * FROM {context_prefix} WHERE prefix = '%s' AND provider = '%s'", $context['prefix'], $context['provider']));
563 if ($context) {
564 return $context;
565 }
566 }
567 return false;
568 }
569 break;
570 case 'validate':
571 if (check_plain($context['provider']) && preg_match('!^[a-z0-9_-]+$!', $context['prefix'])) {
572 $id = db_result(db_query("SELECT id FROM {context_prefix} WHERE prefix = '%s'", $context['prefix']));
573 if ($id && ($id == $context['id'])) {
574 return true;
575 }
576 else if (!$id) {
577 return true;
578 }
579 return false;
580 }
581 else {
582 return false;
583 }
584 case 'insert':
585 if (context_prefix_api('validate', $context)) {
586 $status = db_query("INSERT INTO {context_prefix} (provider, prefix, id) VALUES ('%s', '%s', %d)", $context['provider'], $context['prefix'], $context['id']);
587 return $status;
588 }
589 return false;
590 case 'update':
591 if (context_prefix_api('validate', $context)) {
592 $status = db_query("UPDATE {context_prefix} SET prefix = '%s' WHERE id = '%s' AND provider = '%s'", $context['prefix'], $context['id'], $context['provider']);
593 return $status;
594 }
595 case 'delete':
596 if ($context['prefix']) {
597 $param = 'prefix';
598 $where = $context['prefix'];
599 }
600 else if ($context['id']) {
601 $param = 'id';
602 $where = $context['id'];
603 }
604 $check = db_result(db_query("SELECT id FROM {context_prefix} WHERE provider = '%s' AND $param = '%s'", $context['provider'], $where));
605 if ($check) {
606 $status = db_query("DELETE FROM {context_prefix} WHERE provider = '%s' AND $param = '%s'", $context['provider'], $where);
607 return $status;
608 }
609 return false;
610 }
611 return false;
612 }
613
614 /**
615 * A wrapper around drupal_goto() that abstracts out the prefix/context setting
616 * You provide both a normal drupal path ('node/43') and a context prefix ('dsi')
617 * and context_prefix_goto will determine the correct location to use.
618 */
619 function context_prefix_goto($provider, $id, $path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
620 /**
621 * TODO: we need to abstract this base_url dissection into a
622 * handler, and in there, we'll abstract out for
623 * protocol handling, and handling the site's base_url like www.
624 *
625 * TODO: we need to make sure that other prefixed contexts don't
626 * get dropped. e.g. if you are on 'en/node/43' and you
627 * context_prefix_goto('spaces', 'mygroup'), you should end up
628 * at 'en/mygroup', not 'mygroup'
629 */
630 $method = variable_get('context_prefix_method_'. $provider, CONTEXT_PREFIX_PATH);
631 $prefixes = context_prefix_prefixes($method);
632
633 switch ($method) {
634 case CONTEXT_PREFIX_PATH:
635 foreach ($prefixes as $key => $info) {
636 if ($info['id'] == $id) {
637 clswitch('set', true); // Drop prefixing for context_prefix goto's
638 $path = $key .'/'. $path;
639 break;
640 }
641 }
642 break;
643 case CONTEXT_PREFIX_PAIR:
644 clswitch('set', true);
645 $prefixes = array_keys($prefixes);
646 $path = $prefixes[0] .'/'. $id .'/'. $path;
647 break;
648 case CONTEXT_PREFIX_DOMAIN:
649 foreach ($prefixes as $key => $info) {
650 if ($info['id'] == $id) {
651 $path = 'http://'. $key .'/'. $path;
652 break;
653 }
654 }
655 break;
656 }
657 drupal_goto($path, $query, $fragment, $http_response_code);
658 }
659
660 /**
661 * Custom l wrapper for links that need to leave all group contexts
662 *
663 * TODO: Like context_prefix_goto(), this function needs to allow the
664 * selective dropping/adding of contexts.
665 */
666 function cl($text, $path, $attributes = array(), $query = NULL, $fragment = NULL, $absolute = FALSE, $html = FALSE, $dropcontext = FALSE) {
667 global $base_url;
668 clswitch('set', $dropcontext);
669 if (!$dropcontext && $path == '<front>') {
670 $path = context_prefix_url_rewrite('alias', '', '');
671 }
672 // Handle domains -- need to force domain onto the path and push through as absolute url
673 if ($dropcontext) {
674 $absolute = TRUE;
675 if ($path == '<front>') {
676 $path = variable_get('site_frontpage', 'node');
677 }
678 if ($domain = variable_get('context_prefix_base_domain', '')) {
679 $path = $domain .'/'. $path; // REPLACE BASE_URL with the hub domain.
680 }
681 }
682 $l = l($text, $path, $attributes, $query, $fragment, $absolute, $html);
683 clswitch('reset');
684 return $l;
685 }
686
687 /**
688 * Returns whether the current l/url call should use context rewriting or not
689 */
690 function clswitch($op, $absolute = null) {
691 static $drop;
692 switch ($op) {
693 case 'set';
694 $drop = $absolute;
695 break;
696 case 'get':
697 return $drop;
698 break;
699 case 'reset':
700 $drop = null;
701 break;
702 }
703 }
704
705 /**
706 * Like theme_links, but handles context warping.
707 * theme_links couldn't believe it.
708 */
709 function theme_context_links($links, $attributes = array('class' => 'links')) {
710 $output = '';
711
712 if (count($links) > 0) {
713 $output = '<ul'. drupal_attributes($attributes) .'>';
714
715 $num_links = count($links);
716 $i = 1;
717
718 foreach ($links as $key => $link) {
719 $class = '';
720
721 // Automatically add a class to each link and also to each LI
722 if (isset($link['attributes']) && isset($link['attributes']['class'])) {
723 $link['attributes']['class'] .= ' '. $key;
724 $class = $key;
725 }
726 else {
727 $link['attributes']['class'] = $key;
728 $class = $key;
729 }
730
731 // Add active class for active menu items
732 if (stristr($key, 'active')) {
733 $class .= " active";
734 }
735
736 // Add first and last classes to the list of links to help out themers.
737 $extra_class = '';
738 if ($i == 1) {
739 $extra_class .= 'first ';
740 }
741 if ($i == $num_links) {
742 $extra_class .= 'last ';
743 }
744 $output .= '<li class="'. $extra_class . $class .'">';
745
746 // Is the title HTML?
747 $html = isset($link['html']) && $link['html'];
748
749 // Initialize fragment and query variables.
750 $link['query'] = isset($link['query']) ? $link['query'] : NULL;
751 $link['fragment'] = isset($link['fragment']) ? $link['fragment'] : NULL;
752
753 if (isset($link['href'])) {
754 if ($link['warp']) {
755 $output .= cl($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, $html, TRUE);
756 }
757 else {
758 $output .= l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, $html);
759 }
760 }
761 else if ($link['title']) {
762 //Some links are actually not links, but we wrap these in <span> for adding title and class attributes
763 if (!$html) {
764 $link['title'] = check_plain($link['title']);
765 }
766 $output .= '<span'. drupal_attributes($link['attributes']) .'>'. $link['title'] .'</span>';
767 }
768
769 $i++;
770 $output .= "</li>\n";
771 }
772
773 $output .= '</ul>';
774 }
775
776 return $output;
777 }
778
779 /**
780 * Generates a context prefix form element that can be dropped into a
781 * FormAPI form array. Includes validation, but nsert/update must be
782 * handled by the implementing submit handler.
783 */
784 function context_prefix_form($provider, $id, $prefix = '') {
785 switch (variable_get('context_prefix_method_'. $provider, CONTEXT_PREFIX_PATH)) {
786 case CONTEXT_PREFIX_PATH:
787 case CONTEXT_PREFIX_PAIR:
788 $description = t('Choose a prefix path. May contain only lowercase letters, numbers, dashes and underscores. e.g. "my-prefix"');
789 break;
790 case CONTEXT_PREFIX_SUBDOMAIN:
791 $description = t('Enter a domain registered for this context, such as "mygroup". Do not include http://');
792 break;
793 case CONTEXT_PREFIX_DOMAIN:
794 $description = t('Enter a domain registered for this context, such as "www.example.com". Do not include http://');
795 break;
796 }
797
798 $form = array(
799 '#tree' => TRUE,
800 '#element validate' => array('context_prefix_form_validate'),
801 );
802 $form['prefix'] = array(
803 '#title' => t('Path prefix'),
804 '#type' => 'textfield',
805 '#description' => $description,
806 '#maxlength' => 255,
807 '#required' => true,
808 '#default_value' => $prefix,
809 );
810 $form['provider'] = array(
811 '#type' => 'value',
812 '#value' => $provider,
813 );
814 $form['id'] = array(
815 '#type' => 'value',
816 '#value' => $id,
817 );
818 return $form;
819 }
820
821 /**
822 * Validation handler for context_prefix_form().
823 */
824 function context_prefix_form_validate($form) {
825 $definition = array(
826 'provider' => $form['provider']['#value'],
827 'prefix' => $form['prefix']['#value'],
828 'id' => $form['id']['#value'],
829 );
830 if (!context_prefix_api('validate', $definition)) {
831 form_set_error($form['#parents'][0], t('There was an error registering the prefix "@prefix". It is either invalid or is already taken. Please choose another.', array('@prefix' => $form['prefix']['#value'])));
832 return false;
833 }
834 else {
835 return true;
836 }
837 }
838
839 /**
840 * Specialized cache for storing prefix information.
841 */
842 class context_prefix_cache {
843
844 protected $cache = array();
845
846 function __construct() {
847 $this->cache[CONTEXT_PREFIX_PATH] = array();
848 $this->cache[CONTEXT_PREFIX_PAIR] = array();
849 $this->cache[CONTEXT_PREFIX_SUBDOMAIN] = array();
850 $this->cache[CONTEXT_PREFIX_DOMAIN] = array();
851 }
852
853 /**
854 * @param $method
855 * The method to add to the cache for
856 * @param $item
857 * Either a integer|string, or keyed array to add
858 * @param $merge
859 * Preserve keys and merge into cache for method.
860 */
861 public function add($method, $item, $merge = true) {
862 if (is_array($item) && $merge) {
863 // Need to preserve keys so we use the '+' array operator.
864 $this->cache[$method] = $this->cache[$method] + $item;
865 }
866 else {
867 $this->cache[$method][] = $item;
868 }
869 }
870
871 /**
872 * @param $method
873 * The method to retrieve from the cache for.
874 * @param $item
875 * Optionally and key of the required info.
876 *
877 * @return the desired info or false if an id doesn't exist.
878 */
879 public function get($method = false, $id = false) {
880 if ($method !== false && $id !== false) {
881 return (isset($this->cache[$method][$id]) ? $this->cache[$method][$id] : false);
882 }
883 elseif ($method !== false) {
884 return $this->cache[$method];
885 }
886 else {
887 return $this->cache;
888 }
889 }
890 }
891
892 /**
893 * Helper function, returns form options for prefix types.
894 */
895 function _context_ui_options() {
896 return array(
897 CONTEXT_PREFIX_PATH => t('Path'),
898 CONTEXT_PREFIX_PAIR => t('Keyed pair'),
899 CONTEXT_PREFIX_DOMAIN => t('Full domain'),
900 // CONTEXT_PREFIX_SUBDOMAIN => t('Subdomain'),
901 );
902 }

  ViewVC Help
Powered by ViewVC 1.1.2