Commit b44374f6 authored by boshtian's avatar boshtian

Revert "Clean up Drupal 7 code, prepare for Drupal 8 push."

This reverts commit a1cedf59.
parent a1cedf59
Context 3.x API
---------------
The following is an overview of using the Context API.
The context static cache
------------------------
Context provides a centralized set of API functions for setting and retrieving a
static cache:
// Set a static cache value at [my_namspace][mykey]
context_set('my_namespace', 'mykey', $value);
// Retrieve a static cache value at [my_namespace][mykey]
context_get('my_namespace', 'mykey'); // $value
// Boolean for whether there is a value at [my_namespace][mykey]
context_isset('my_namespace', 'mykey'); // TRUE
These are used internally by context but may also be used by other modules. Just
do not use the namespace `context` unless you want to affect things that context
is up to.
Adding a condition or reaction plugin
-------------------------------------
Both context conditions and reactions utilize the CTools plugins API. In order
to add a new condition or reaction for your module, follow these steps:
1. Implement `hook_context_plugins()` to define your plugins, classes, and class
hierarchy.
function mymodule_context_plugins() {
$plugins = array();
$plugins['mymodule_context_condition_bar'] = array(
'handler' => array(
'path' => drupal_get_path('module', 'mymodule') .'/plugins',
'file' => 'mymodule_context_condition_bar.inc',
'class' => 'mymodule_context_condition_bar',
'parent' => 'context_condition',
),
);
return $plugins;
}
2. Implement `hook_context_registry()` to define your conditions and/or
reactions and map them to plugins.
function mymodule_context_registry() {
return array(
'conditions' => array(
'bar' => array(
'title' => t('Name of condition "bar"'),
'plugin' => 'mymodule_context_condition_bar',
),
),
);
}
3. Write your condition or reaction plugin class. It's best to look at one of
the included plugins as a starting point.
4. Create a Drupal integration point for your plugin. A node page condition
plugin, for example, may be invoked from `hook_node_view()`. Typically a
Drupal integration point for a condition uses a Drupal hook to trigger
tests that determine whether context conditions are met for one or more
plug-ins. For example, this is how the context module itself uses
hook_init():
function context_init() {
if ($plugin = context_get_plugin('condition', 'path')) {
$plugin->execute();
}
if ($plugin = context_get_plugin('condition', 'language')) {
global $language;
$plugin->execute($language->language);
}
if ($plugin = context_get_plugin('condition', 'user')) {
global $user;
$plugin->execute($user);
}
}
This function first instantiates the Context module's path condition
plugin (filename context_condition_path.inc in the plugins directory),
and then uses that plugin's execute() method. The execute() method
determine whether any path conditions are met and, if so, it activates
the contexts that match those conditions. After setting contexts based
path conditions, the context_init() function then does the same thing
with the Context module's language and user condition plugins.
Replacing or extending existing plugins
---------------------------------------
You can replace a condition or reaction plugin with your own plugin class using
`hook_context_registry_alter()`:
function mymodule_context_registry_alter(&$registry) {
if (!empty($registry['conditions']['node'])) {
$registry['conditions']['node']['plugin'] = 'mymodule_context_condition_customnode';
}
}
This entry would swap out the default node condition plugin for a custom one
provided by `mymodule`. Note that any replacement plugins must have an entry in
`hook_context_plugins()`.
Current state of Context for Drupal 7
-------------------------------------
Context for D7 is a straight port of Context 3.x from D6. There are no major
API changes and any exported contexts from D6 should be compatible with the D7
version. You will need the latest CTools (as of Sept. 16 2010) from here:
- http://github.com/sdboyer/ctools
### Working
- all conditions except node taxonomy condition
- all reactions
- context UI
- context layouts
- inline editor (see the context_ui README file for info on enabling)
### Expect API changes
- node taxonomy condition to generic field condition for entities
Context 3.x for Drupal 7.x
--------------------------
Context allows you to manage contextual conditions and reactions for
different portions of your site. You can think of each context as
representing a "section" of your site. For each context, you can choose
the conditions that trigger this context to be active and choose different
aspects of Drupal that should react to this active context.
Think of conditions as a set of rules that are checked during page load
to see what context is active. Any reactions that are associated with
active contexts are then fired.
Installation
------------
Context can be installed like any other Drupal module -- place it in
the modules directory for your site and enable it (and its requirement,
CTools) on the `admin/modules` page.
You will probably also want to install Context UI which provides a way for
you to edit contexts through the Drupal admin interface.
Example
-------
You want to create a "pressroom" section of your site. You have a press
room view that displays press release nodes, but you also want to tie
a book with media resources tightly to this section. You would also
like a contact block you've made to appear whenever a user is in the
pressroom section.
1. Add a new context on admin/structure/context
2. Under "Conditions", associate the pressroom nodetype, the pressroom view,
and the media kit book with the context.
3. Under "Reactions > Menu", choose the pressroom menu item to be set active.
4. Under "Reactions > Blocks", add the contact block to a region.
5. Save the context.
For a more in-depth overview of the UI components, see the Context UI
`README.txt`.
Hooks
-----
See `context.api.php` for the hooks made available by context and `API.txt` for
usage examples.
Maintainers
-----------
- yhahn (Young Hahn)
- jmiccolis (Jeff Miccolis)
- Steven Jones
Contributors
------------
- alex_b (Alex Barth)
- dmitrig01 (Dmitri Gaskin)
- Pasqualle (Csuthy Bálint)
<?php
/**
* @file
* Hooks provided by Context.
*/
/**
* CTools plugin API hook for Context. Note that a proper entry in
* hook_ctools_plugin_api() must exist for this hook to be called.
*/
function hook_context_plugins() {
$plugins = array();
$plugins['foo_context_condition_bar'] = array(
'handler' => array(
'path' => drupal_get_path('module', 'foo') .'/plugins',
'file' => 'foo_context_condition_bar.inc',
'class' => 'foo_context_condition_bar',
'parent' => 'context_condition',
),
);
$plugins['foo_context_reaction_baz'] = array(
'handler' => array(
'path' => drupal_get_path('module', 'foo') .'/plugins',
'file' => 'foo_context_reaction_baz.inc',
'class' => 'foo_context_reaction_baz',
'parent' => 'context_reaction',
),
);
return $plugins;
}
/**
* Registry hook for conditions & reactions.
*
* Each entry associates a condition or reaction with the CTools plugin to be
* used as its plugin class.
*/
function hook_context_registry() {
return array(
'conditions' => array(
'bar' => array(
'title' => t('Name of condition "bar"'),
'plugin' => 'foo_context_condition_bar',
),
),
'reactions' => array(
'baz' => array(
'title' => t('Name of reaction "baz"'),
'plugin' => 'foo_context_reaction_baz',
),
),
);
}
/**
* Execute Context page conditions
*
* Allows modules to hook into Context's hook_page_build to execute their
* conditions at an appropriate time before the firing of reactions.
*/
function hook_context_page_condition() {
if ($plugin = context_get_plugin('condition', 'bar')) {
$plugin->execute();
}
}
/**
* Execute Context page reactions
*
* Allows modules to hook into Context's hook_page_build to execute their
* reactions at an appropriate time after the firing of conditions.
*/
function hook_context_page_reaction() {
if ($plugin = context_get_plugin('reaction', 'baz')) {
$plugin->execute();
}
}
/**
* Alter the registry.
*
* Allows modules to alter the registry. Default plugins can be replaced by
* custom ones declared in hook_context_plugins().
*
* @param $registry
* The registry, passed by reference.
*/
function hook_context_registry_alter(&$registry) {
if (isset($registry['reactions']['baz'])) {
$registry['reactions']['baz']['plugin'] = 'custom_context_reaction_baz';
}
}
/**
* Alter/add a condition to a node-related event.
*
* Allows modules to add one or more context condition plugin executions to a
* node view, form, etc.
*
* @param $node
* The node object.
* @param $op
* The node-related operation: 'node', 'form', 'comment'.
*/
function hook_context_node_condition_alter(&$node, $op) {
if ($plugin = context_get_plugin('condition', 'bar')) {
$plugin->execute($node, $op);
}
}
/**
* Alter a context directly after it has been loaded. Allows modules to alter
* a context object's reactions. While you may alter conditions, this will
* generally have no effect as conditions are cached for performance and
* contexts are loaded after conditions are checked, not before.
*
* @param &$context
* The context object by reference.
*/
function hook_context_load_alter(&$context) {
if ($context->name === 'foo' && isset($context->reactions['block'])) {
$context->reactions['block']['blocks']['locale-0'] = array(
'module' => 'locale',
'delta' => '0',
'region' => 'header',
'weight' => '2',
);
}
}
/**
* Allows for finer grained access mechanisms to using the json
* rendering capabilities of the block reaction when a user isn't
* granted the administer contexts or context ajax block access
* permission
* @param $block_id
* ID of block in module-delta format
*/
function hook_context_allow_ajax_block_access($block_id) {
}
<?php
/**
* Implementation of hook_help().
*/
function context_help($path, $arg) {
switch ($path) {
case 'admin/help#context':
$output = file_get_contents(drupal_get_path('module', 'context') . '/README.txt');
return module_exists('markdown') ? filter_xss_admin(module_invoke('markdown', 'filter', 'process', 0, -1, $output)) : '<pre>' . check_plain($output) . '</pre>';
}
}
/**
* Implementation of hook_theme().
*/
function context_theme() {
$items = array();
if (!module_exists('block')) {
$items['block'] = array(
'render element' => 'elements',
'template' => 'block',
'path' => drupal_get_path('module', 'block'),
'file' => 'block.module',
'template' => 'block',
);
}
$items['context_block_form'] = array(
'render element' => 'form',
'path' => drupal_get_path('module', 'context') . '/theme',
'file' => 'context_reaction_block.theme.inc',
);
$items['context_block_regions_form'] = array(
'render element' => 'form',
'path' => drupal_get_path('module', 'context') . '/theme',
'file' => 'context_reaction_block.theme.inc',
);
$items['context_block_editor'] = array(
'render element' => 'form',
'path' => drupal_get_path('module', 'context') . '/theme',
'file' => 'context_reaction_block.theme.inc',
);
$items['context_block_browser'] = array(
'variables' => array('blocks' => array(), 'context' => array()),
'path' => drupal_get_path('module', 'context') . '/theme',
'template' => 'context-block-browser',
'file' => 'context_reaction_block.theme.inc',
);
$items['context_block_browser_item'] = array(
'variables' => array('block' => array()),
'path' => drupal_get_path('module', 'context') . '/theme',
'template' => 'context-block-browser-item',
'file' => 'context_reaction_block.theme.inc',
);
$items['context_block_script_placeholder'] = array(
'variables' => array('text' => NULL),
'path' => drupal_get_path('module', 'context') . '/theme',
'file' => 'context_reaction_block.theme.inc',
);
$items['context_block_edit_wrap'] = array(
'render element' => 'element',
'path' => drupal_get_path('module', 'context') . '/theme',
'file' => 'context_reaction_block.theme.inc',
);
return $items;
}
/**
* Implementation of hook_theme_registry_alter().
*/
function context_theme_registry_alter(&$theme_registry) {
// Push theme_page() through a context_preprocess to provide
// context-sensitive menus and variables. Ensure that
// context_preprocess_page() comes immediately after
// template_preprocess_page().
$position = array_search('context_preprocess_page', $theme_registry['page']['preprocess functions']);
if ($position !== FALSE) {
unset($theme_registry['page']['preprocess functions'][$position]);
}
// Prevent conflict with i18n_menu.
if (module_exists('i18n_menu')) {
$position = array_search('i18n_menu_preprocess_page', $theme_registry['page']['preprocess functions']);
}
else {
$position = array_search('template_preprocess_page', $theme_registry['page']['preprocess functions']);
}
$position = $position ? $position + 1 : 2;
array_splice($theme_registry['page']['preprocess functions'], $position, 0, 'context_preprocess_page');
}
/**
* Implementation of hook_ctools_render_alter().
* Used to detect the presence of a page manager node view or node form.
*/
function context_ctools_render_alter($info, $page, $data) {
extract($data);
if ($page && in_array($task['name'], array('node_view', 'node_edit'), TRUE)) {
foreach ($contexts as $ctools_context) {
if (in_array('node', $ctools_context->type) && !empty($ctools_context->data)) {
context_node_condition($ctools_context->data, $task['name'] === 'node_view' ? 'view' : 'form');
break;
}
}
}
}
/**
* Implementation of hook_entity_prepare_view().
*/
function context_entity_prepare_view($prepare, $entity_type) {
if ($entity_type === 'taxonomy_term' && count($prepare) === 1) {
$term = reset($prepare);
$menu = menu_get_object('taxonomy_term', 2);
if ($menu && $term->tid == $menu->tid && $plugin = context_get_plugin('condition', 'taxonomy_term')) {
$plugin->execute($term, 'view');
}
}
}
/**
* Implementation of hook_node_view().
*/
function context_node_view($node, $view_mode) {
$object = menu_get_object();
if (isset($object->nid) && $object->nid === $node->nid) {
context_node_condition($node, 'view');
}
}
/**
* Implementation of hook_form_alter().
*/
function context_form_alter(&$form, $form_state, $form_id) {
// If the form is an admin for, flag it so that we can force a rebuild if needed.
if (path_is_admin($_GET['q'])) {
$form['#submit'][] = 'context_admin_form_submit';
}
// Trigger the condition in an after_build function to avoid being skipped
// when there are validation errors.
$form['#after_build'][] = 'context_form_alter_node_after_build';
}
/**
* Form #after_build callback for context_form_alter().
*/
function context_form_alter_node_after_build($form, &$form_state) {
// Prevent this from firing on admin pages... damn form driven apis...
if (!empty($form['#node_edit_form']) && arg(0) != 'admin') {
context_node_condition($form['#node'], 'form');
}
return $form;
}
/**
* Clear out block info cache when an admin area form is submitted.
*/
function context_admin_form_submit(&$form, $form_state) {
if ($plugin = context_get_plugin('reaction', 'block')) {
$plugin->rebuild_needed(TRUE);
}
}
/**
* Centralized node condition call function for the ever increasing number of
* ways to get at a node view / node form.
*/
function context_node_condition(&$node, $op) {
if ($plugin = context_get_plugin('condition', 'node')) {
$plugin->execute($node, $op);
}
if (module_exists('taxonomy')) {
if ($plugin = context_get_plugin('condition', 'node_taxonomy')) {
$plugin->execute($node, $op);
}
}
if (module_exists('book')) {
if ($plugin = context_get_plugin('condition', 'book')) {
$plugin->execute($node, $op);
}
if ($plugin = context_get_plugin('condition', 'bookroot')) {
$plugin->execute($node, $op);
}
}
// Allow other plugins to easily be triggered on node-related events.
drupal_alter('context_node_condition', $node, $op);
}
/**
* Implementation of hook_form_alter() for system_modules_form.
*/
function context_form_system_modules_form_alter(&$form, $form_state) {
context_invalidate_cache();
}
/**
* Implementation of hook_form_alter() for user_profile_form.
*/
function context_form_user_profile_form_alter(&$form, $form_state) {
if ($plugin = context_get_plugin('condition', 'user_page')) {
$plugin->execute($form['#user'], 'form');
}
}
/**
* Implementation of hook_form_alter() for user_register_form.
*/
function context_form_user_register_form_alter(&$form, $form_state) {
if ($plugin = context_get_plugin('condition', 'user_page')) {
$plugin->execute($form['#user'], 'register');
}
}
/**
* Implementation of hook_form_alter() for comment_form.
*/
function context_form_comment_form_alter(&$form, $form_state) {
if ($nid = $form['nid']['#value']) {
$node = node_load($nid);
context_node_condition($node, 'comment');
}
}
/**
* Implementation of hook_views_pre_view().
*/
function context_views_pre_view($view, $display) {
if ($plugin = context_get_plugin('condition', 'views')) {
$plugin->execute($view);
}
// Support Views overrides of specific entity paths.
if ($view->display_handler->has_path()) {
switch ($view->display_handler->get_option('path')) {
case 'taxonomy/term/%':
if (($term = taxonomy_term_load(arg(2))) && ($plugin = context_get_plugin('condition', 'taxonomy_term'))) {
$plugin->execute($term, 'view');
}
break;
case 'node/%':
if ($node = node_load(arg(1))) {
context_node_condition($node, 'view');
}
break;
case 'user/%':
if (($account = user_load(arg(1))) && ($plugin = context_get_plugin('condition', 'user_page'))) {
$plugin->execute($account, 'view');
}
break;
}
}
}
/**
* Implementation of hook_user().
*/
function context_user_view($account, $view_mode) {
if ($view_mode === 'full' && $plugin = context_get_plugin('condition', 'user_page')) {
$plugin->execute($account, 'view');
}
}
/**
* Implements hook_page_build().
*/
function context_page_build(&$page) {
module_invoke_all('context_page_condition');
module_invoke_all('context_page_reaction');
if ($plugin = context_get_plugin('reaction', 'block')) {
$plugin->execute($page);
}
// See block_page_build. Clear static cache b/c in overlay form submissions
// hook_page_build can get called more than once per page load.
drupal_static_reset('context_reaction_block_list');
}
/**
* THEME FUNCTIONS & RELATED ==========================================
*/
/**
* Generates an array of links (suitable for use with theme_links)
* to the node forms of types associated with current active contexts.
*/
function context_links($reset = FALSE) {
static $links;
if (!$links || $reset) {
$contexts = context_active_contexts();
$active_types = array();
$conditions = array('node', 'bookroot');