Commit a9885e2e authored by boshtian's avatar boshtian

Merge branch '8.x-1.x' into 8.x-4.x in order to use this branch and remove '8.x-1.x' in future.

parents b44374f6 e3356199
# This file is for unifying the coding style for various code editors and IDEs.
# Make sure to have an editorconfig plug-in installed in your editor to have
# the editor use this file.
# Sets this config file to be the top-most one.
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
\ No newline at end of file
.DS_Store
language: php
sudo: false
php:
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
allow_failures:
- php: hhvm
fast_finish: true
mysql:
database: context
username: root
encoding: utf8
before_script:
# Remember the current context test directory for later use in the Drupal
# installation.
- TESTDIR=$(pwd)
# Navigate out of module directory to prevent blown stack by recursive module
# lookup.
- cd ..
# Create database.
- mysql -e 'create database context'
# Export database variable for kernel tests.
- export SIMPLETEST_DB=mysql://root:@127.0.0.1/context
# Download Drupal 8 core.
- travis_retry git clone --branch 8.0.x --depth 1 http://git.drupal.org/project/drupal.git
- cd drupal
# Reference rules in build site.
- ln -s $TESTDIR modules/context
script:
# Run the PHPUnit tests which also include the kernel tests.
- ./vendor/phpunit/phpunit/phpunit -c ./core/phpunit.xml.dist ./modules/context
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()`.
# Change log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
# Contributing
This file will contain information on how you can contribute to the project.
The MIT License (MIT)
Copyright (c) 2015 Odd Hill
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Context
The context module lets you define conditions for when certain reactions should take place.
An example of a condition could be when viewing a certain node type and blocks should be placed as a reaction when viewing a page with this node type.
###Good resources
- [Drupal 8 Plugin API](https://www.drupal.org/developing/api/8/plugins)
Conditions
---
Context for Drupal 8 uses the built in condition plugins supplied by Drupal through the [Plugin API](https://www.drupal.org/developing/api/8/plugins). So any conditional plug-ins supplied by other modules can also be used with context.
Reactions
---
Reactions for the context module are defined trough the new Drupal 8 [Plugin API](https://www.drupal.org/developing/api/8/plugins).
The context module defines a plugin type named Context Reaction that you can extend when creating your own plugins.
A context reaction requires a configuration form and execute method. The execution of the plugin is also something that will have to be handled by the author of the reaction.
\ No newline at end of file
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)
{
"name": "drupal/context",
"description": "Manage contextual conditions and reactions for different portions of your site.",
"keywords": ["Drupal", "context", "block", "visibility", "conditions"],
"type": "drupal-module",
"license": "MIT",
"homepage": "https://github.com/oddhill/context",
"authors": [
{
"name": "Christoffer Palm",
"email": "christoffer.palm@oddhill.se",
"homepage": "http://www.oddhill.se/",
"role": "Developer"
}
],
"support": {
"issues": "https://github.com/oddhill/context/issues",
"source": "https://github.com/oddhill/context",
"docs": "https://github.com/oddhill/context"
}
}
<?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')) {