Commit a8c266ce authored by Pietro Albini's avatar Pietro Albini

Added Panels module

parent 75088b13
Current API Version: 2.0.8
Please note that the API version is an internal number and does not match release numbers. It is entirely possible that releases will not increase the API version number, and increasing this number too often would burden contrib module maintainers who need to keep up with API changes.
This file contains a log of changes to the API.
API Version 2.0.8
Introduce ctools_class_add().
Introduce ctools_class_remove().
API Version 2.0.7
All ctools object cache database functions can now accept session_id as an optional
argument to facilitate using non-session id keys.
API Version 2.0.6
Introduce a hook to alter the implementors of a certain api via hook_[ctools_api_hook]_alter.
API Version 2.0.5
Introduce ctools_fields_get_fields_by_type().
Add language.inc
Introduce hook_ctools_content_subtype_alter($subtype, $plugin);
API Version 2.0.4
Introduce ctools_form_include_file()
API Version 2.0.3
Introduce ctools_field_invoke_field() and ctools_field_invoke_field_default().
API Version 2.0.2
Introduce ctools_export_crud_load_multiple() and 'load multiple callback' to
export schema.
API Version 2.0.1
Introduce ctools_export_crud_enable(), ctools_export_crud_disable() and
ctools_export_crud_set_status() and requisite changes.
Introduce 'object factory' to export schema, allowing modules to control
how the exportable objects are instantiated.
Introduce 'hook_ctools_math_expression_functions_alter'.
API Version 2.0
Remove the deprecated callback-based behavior of the 'defaults' property on
plugin types; array addition is now the only option. If you need more
complex logic, do it with the 'process' callback.
Introduce a global plugin type registration hook and remove the per-plugin
type magic callbacks.
Introduce $owner . '_' . $api . '_hook_name' allowing modules to use their own
API hook in place of 'hook_ctools_plugin_api'.
Introduce ctools_plugin_api_get_hook() to get the hook name above.
Introduce 'cache defaults' and 'default cache bin' keys to export.inc
Versions prior to 2.0 have been removed from this document. See the D6 version
for that information.
Current API VERSION: 2.0. See API.txt for more information.
ctools 7.x-1.x-dev
==================
#1008120: "New custom content" shows empty form if custom content panes module is not enabled.
#999302 by troky: Fix jump menu. Apparently this wasn't actually committed the last time it was committed.
#1065976 by tekante and David_Rothstein: Reset plugin static cache during module enable to prevent stale data from harming export ui.
#1016510 by EclipseGC: Make the taxonomy system page functional.
ctools 7.x-1.x-alpha2 (05-Jan-2011)
===================================
#911396 by alex_b: Prevent notices in export UI.
#919768 by mikey_p: Allow url options to be sent to ctools_ajax_command_url().
#358953 by cedarm: Allow term context to return lowercase, spaces to dashes versions of terms.
#931434 by EclipseGc: Argument plugin for node revision ID.
#910656: CTools AJAX sample wizard demo "domesticated" checkbox value not stored.
#922442 by EugenMayer, neclimdul and voxpelli: Make sure ctools_include can handle '' or NULL directory.
#919956 by traviss359: Correct example in wizard advanced help.
#942968: Fix taxonomy term access rule with tag term vocabs.
#840344: node add argument had crufty code causing notices.
#944462 by longhairedgit: Invalid character in regex causes rare notice.
#938778 by dereine: Fix profile content type for D7 updates.
Add detach event to modal close so that wysiwyg can detach the editor.
Variant titles showing up as blank if more than one variant on a page.
#940016: token support was not yet updated for D7.
#940446: Skip validation on back and cancel buttons in all wizards.
#954492: Redirect not always working in wizard.inc
#955348: Lack of redirect on "Update" button in Page Manager causing data loss sometimes.
#941778: Update and save button should not appear in the "Add variant" path.
#955070 by EclipseGc: Update ctools internal page tokens to work properly on content all content.
#956890 by EclipseGc: Update views_content to not use views dependency since that is gone.
#954728 by EclipseGc: Update node template page function name to not collide with new hook_node_view().
#946534 by EclipseGc: Add support for field content on all entitities.
#952586 by EclipseGc: Fix node_author content type.
#959206: If a context is not set when rendering content, attempt to guess the context (fixes Views panes where "From context" was added but pane was never edited.)
#961654 by benshell: drupal_alter() only supports 4 arguments.
#911362 by alex_b: Facilitate plugin cache resets for tests.
#945360 by naxoc: node_tag_new() not updated to D7.
#953804 by EclipseGc: Fix node comment rendering.
#953542 by EclipseGc: Fix node rendering.
#953776 by EclipseGc: Fix node link rendering.
#954772 by EclipseGc: Fix node build mode selection in node content type.
#954762 by EclipseGc: Fix comment forbidden theme call.
#954894 by EclipseGc: Fix breadcrumb content type.
#955180 by EclipseGc: Fix page primary navigation type.
#957190 by EclipseGc: Fix page secondary navigation type.
#957194 by EclipseGc: Remove mission content type, since D7 no longer has a site mission.
#957348 by EclipseGc: Fix search form URL path.
#952586 by andypost: Use format_username for displaying unlinked usernames.
#963800 by benshell: Fix query to fetch custom block title.
#983496 by Amitaibu: Fix term argument to use proper load function.
#989484 by Amitaibu: Fix notice in views plugin.
#982496: Fix token context.
#995026: Fix export UI during enable/disable which would throw notices and not properly set/unset menu items.
#998870 by Amitaibu: Fix notice when content has no icon by using function already designed for that.
#983576 by Amitaibu: Node view fallback task showed white screen.
#1004644 by pillarsdotnet: Update a missed theme() call to D7.
#1006162 by aspilicious: .info file cleanup.
#998312 by dereine: Support the expanded/hidden options that Views did for dependent.js
#955030: Remove no longer supported footer message content type.
Fix broken query in term context config.
#992022 by pcambra: Fix node autocomplete.
#946302 by BerdArt and arywyr: Fix PHP 5.3 reference error.
#980528 by das-peter: Notice fix with entity settings.
#999302 by troky: ctools_jump_menu() needed updating to new form parameters.
#964174: stylizer plugin theme delegation was in the wrong place, causing errors.
#991658 by burlap: Fully load the "user" context for the logged in user because not all fields are in $user.
#1014866 by das-peter: Smarter title panes, notice fix on access plugin descriptions.
#1015662 by troky: plugin .info files were not using correct filepaths.
#941780 by EclipseGc: Restore the "No blocks" functionality.
#951048 by EclipseGc: Tighter entity integration so that new entities are automatic contexts and relationships.
#941800 by me and aspilicious: Use Drupal 7 #machine_name automation on page manager pages and all export_ui defaults.
Disabled exportables and pages not properly greyed out.
#969208 by me and benshell: Get user_view and user profile working.
#941796: Recategorize blocks
ctools 7.x-1.x-alpha1
=====================
Changelog reset for 7.x
Basic conversion done during sprint.
This diff is collapsed.
Upgrading from ctools-6.x-1.x to ctools-7.x-2.x:
- Remove ctools_ajax_associate_url_to_element as it shouldn't be necessary
with the new AJAX api's in Drupal core.
- All calls to the ctools_ajax_command_prepend() should be replace with
the core function ajax_command_prepend();
This is also the case for append, insert, after, before, replace, html,
and remove commands.
Each of these commands have been incorporated into the
Drupal.ajax.prototype.commands.insert
function with a corresponding parameter specifying which method to use.
- All calls to ctools_ajax_render() should be replaced with calls to core
ajax_render(). Note that ctools_ajax_render() printed the json object and
exited, ajax_render() gives you this responsibility.
ctools_ajax_render()
becomes
print ajax_render();
exit;
- All calls to ctools_static*() should be replaced with corresponding calls
to drupal_static*().
- All calls to ctools_css_add_css should be replaced with calls to
drupal_add_css(). Note that the arguments to drupal_add_css() have changed.
- All wizard form builder functions must now return a form array().
- ctools_build_form is very close to being removed. In anticipation of this,
all $form_state['wrapper callback']s must now be
$form_state['wrapper_callback']. In addition to this $form_state['args']
must now be $form_state['build_info']['args'].
NOTE: Previously checking to see if the return from ctools_build_form()
is empty would be enough to see if the form was submitted. This is no
longer true. Please check for $form_state['executed']. If using a wizard
check for $form_state['complete'].
- Plugin types now must be explicitly registered via a registration hook,
hook_ctools_plugin_type(); info once provided in magically-named functions
(e.g., ctools_ctools_plugin_content_types() was the old function to
provide plugin type info for ctools' content_type plugins) now must be
provided in that global hook. See http://drupal.org/node/910538 for more
details.
- Plugins that use 'theme arguments' now use 'theme variables' instead.
- Context, argument and relationship plugins now use 'add form' and/or
'edit form' rather than 'settings form'. These plugins now support
form wizards just like content plugins. These forms now all take
$form, &$form_state as arguments, and the configuration for the plugin
can be found in $form_state['conf'].
For all these forms, the submit handler MUST put appropriate data in
$form_state['conf']. Data will no longer be stored automatically.
For all of these forms, the separate settings #trees in the form are now
gone, so form ids may be adjusted. Also, these are now all real forms
using CTools form wizard instead of fake subforms as previously.
\ No newline at end of file
.export-container {
width: 48%;
float: left;
padding: 5px 1% 0;
}
.export-container table {
width: 100%;
}
.export-container table input,
.export-container table th,
.export-container table td {
padding: 0 0 .2em .5em;
margin: 0;
vertical-align: middle;
}
.export-container .select-all {
width: 1.5em;
}
name = Bulk Export
description = Performs bulk exporting of data objects known about by Chaos tools.
core = 7.x
dependencies[] = ctools
package = Chaos tool suite
; Information added by drupal.org packaging script on 2013-04-03
version = "7.x-1.3"
core = "7.x"
project = "ctools"
datestamp = "1365013512"
/**
* @file
* CTools Bulk Export javascript functions.
*/
(function ($) {
Drupal.behaviors.CToolsBulkExport = {
attach: function (context) {
$('#bulk-export-export-form .vertical-tabs-pane', context).drupalSetSummary(function (context) {
// Check if any individual checkbox is checked.
if ($('.bulk-selection input:checked', context).length > 0) {
return Drupal.t('Exportables selected');
}
return '';
});
// Special bind click on the select-all checkbox.
$('.select-all').bind('click', function(context) {
$(this, '.vertical-tabs-pane').drupalSetSummary(context);
});
}
};
})(jQuery);
<?php
/**
* @file
* Perform bulk exports.
*/
/**
* Implements hook_permission().
*/
function bulk_export_permission() {
return array(
'use bulk exporter' => array(
'title' => t('Access Bulk Exporter'),
'description' => t('Export various system objects into code.'),
),
);
}
/**
* Implements hook_menu().
*/
function bulk_export_menu() {
$items['admin/structure/bulk-export'] = array(
'title' => 'Bulk Exporter',
'description' => 'Bulk-export multiple CTools-handled data objects to code.',
'access arguments' => array('use bulk exporter'),
'page callback' => 'bulk_export_export',
);
$items['admin/structure/bulk-export/results'] = array(
'access arguments' => array('use bulk exporter'),
'page callback' => 'bulk_export_export',
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* FAPI gateway to the bulk exporter.
*
* @param $cli
* Whether this function is called from command line.
* @param $options
* A collection of options, only passed in by drush_ctools_export().
*/
function bulk_export_export($cli = FALSE, $options = array()) {
ctools_include('export');
$form = array();
$schemas = ctools_export_get_schemas(TRUE);
$exportables = $export_tables = array();
foreach ($schemas as $table => $schema) {
if (!empty($schema['export']['list callback']) && function_exists($schema['export']['list callback'])) {
$exportables[$table] = $schema['export']['list callback']();
}
else {
$exportables[$table] = ctools_export_default_list($table, $schema);
}
natcasesort($exportables[$table]);
$export_tables[$table] = $schema['module'];
}
if ($exportables) {
$form_state = array(
're_render' => FALSE,
'no_redirect' => TRUE,
'exportables' => $exportables,
'export_tables' => $export_tables,
'name' => '',
'code' => '',
'module' => '',
);
// If called from drush_ctools_export, get the module name and
// select all exportables and call the submit function directly.
if ($cli) {
$module_name = $options['name'];
$form_state['values']['name'] = $module_name;
if (isset($options['selections'])) {
$exportables = $options['selections'];
}
$form_state['values']['tables'] = array();
foreach ($exportables as $table => $names) {
if (!empty($names)) {
$form_state['values']['tables'][] = $table;
$form_state['values'][$table] = array();
foreach ($names as $name => $title) {
$form_state['values'][$table][$name] = $name;
}
}
}
$output = bulk_export_export_form_submit($form, $form_state);
}
else {
$output = drupal_build_form('bulk_export_export_form', $form_state);
$module_name = $form_state['module'];
}
if (!empty($form_state['submitted']) || $cli) {
drupal_set_title(t('Bulk export results'));
$output = '';
$module_code = '';
$api_code = array();
$dependencies = $file_data = array();
foreach ($form_state['code'] as $module => $api_info) {
if ($module == 'general') {
$module_code .= $api_info;
}
else {
foreach ($api_info as $api => $info) {
$api_hook = ctools_plugin_api_get_hook($module, $api);
if (empty($api_code[$api_hook])) {
$api_code[$api_hook] = '';
}
$api_code[$api_hook] .= " if (\$module == '$module' && \$api == '$api') {\n";
$api_code[$api_hook] .= " return array('version' => $info[version]);\n";
$api_code[$api_hook] .= " }\n";
$dependencies[$module] = TRUE;
$file = $module_name . '.' . $api . '.inc';
$code = "<?php\n\n";
$code .= "/**\n";
$code .= " * @file\n";
$code .= " * Bulk export of $api objects generated by Bulk export module.\n";
$code .= " */\n\n";
$code .= $info['code'];
if ($cli) {
$file_data[$file] = $code;
}
else {
$export_form = drupal_get_form('ctools_export_form', $code, t('Place this in @file', array('@file' => $file)));
$output .= drupal_render($export_form);
}
}
}
}
// Add hook_ctools_plugin_api at the top of the module code, if there is any.
if ($api_code) {
foreach ($api_code as $api_hook => $text) {
$api = "\n/**\n";
$api .= " * Implements hook_$api_hook().\n";
$api .= " */\n";
$api .= "function {$module_name}_$api_hook(\$module, \$api) {\n";
$api .= $text;
$api .= "}\n";
$module_code = $api . $module_code;
}
}
if ($module_code) {
$module = "<?php\n\n";
$module .= "/**\n";
$module .= " * @file\n";
$module .= " * Bulk export of objects generated by Bulk export module.\n";
$module .= " */\n";
$module .= $module_code;
if ($cli) {
$file_data[$module_name . '.module'] = $module;
}
else {
$export_form = drupal_get_form('ctools_export_form', $module, t('Place this in @file', array('@file' => $form_state['module'] . '.module')));
$output = drupal_render($export_form) . $output;
}
}
$info = strtr("name = @module export module\n", array('@module' => $form_state['module']));
$info .= strtr("description = Export objects from CTools\n", array('@module' => $form_state['values']['name']));
foreach ($dependencies as $module => $junk) {
$info .= "dependencies[] = $module\n";
}
$info .= "package = Chaos tool suite\n";
$info .= "core = 7.x\n";
if ($cli) {
$file_data[$module_name . '.info'] = $info;
}
else {
$export_form = drupal_get_form('ctools_export_form', $info, t('Place this in @file', array('@file' => $form_state['module'] . '.info')));
$output = drupal_render($export_form) . $output;
}
}
if ($cli) {
return $file_data;
}
else {
return $output;
}
}
else {
return t('There are no objects to be exported at this time.');
}
}
/**
* FAPI definition for the bulk exporter form.
*
*/
function bulk_export_export_form($form, &$form_state) {
$files = system_rebuild_module_data();
$form['additional_settings'] = array(
'#type' => 'vertical_tabs',
);
$options = $tables = array();
foreach ($form_state['exportables'] as $table => $list) {
if (empty($list)) {
continue;
}
foreach ($list as $id => $title) {
$options[$table][$id] = array($title);
$options[$table][$id]['#attributes'] = array('class' => array('bulk-selection'));
}
$module = $form_state['export_tables'][$table];
$header = array($table);
$module_name = $files[$module]->info['name'];
$tables[] = $table;
if (!isset($form[$module_name])) {
$form[$files[$module]->info['name']] = array(
'#type' => 'fieldset',
'#group' => 'additional_settings',
'#title' => $module_name,
);
}
$form[$module_name]['tables'][$table] = array(
'#prefix' => '<div class="export-container">',
'#suffix' => '</div>',
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options[$table],
);
}
$form['tables'] = array(
'#type' => 'value',
'#value' => $tables,
);
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Module name'),
'#description' => t('Enter the module name to export code to.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Export'),
);
$form['#action'] = url('admin/structure/bulk-export/results');
$form['#attached']['css'][] = drupal_get_path('module', 'bulk_export') . '/bulk_export.css';
$form['#attached']['js'][] = drupal_get_path('module', 'bulk_export') . '/bulk_export.js';
return $form;
}
/**
* Process the bulk export submit form and make the results available.
*/
function bulk_export_export_form_submit($form, &$form_state) {
$code = array();
$name = empty($form_state['values']['name']) ? 'foo' : $form_state['values']['name'];
$tables = $form_state['values']['tables'];
foreach ($tables as $table) {
$names = array_keys(array_filter($form_state['values'][$table]));
if ($names) {
natcasesort($names);
ctools_export_to_hook_code($code, $table, $names, $name);
}
}
$form_state['code'] = $code;
$form_state['module'] = $name;
}
.ctools-button-processed {
border-style: solid;
border-width: 1px;
display: inline-block;
line-height: 1;
}
.ctools-button-processed:hover {
cursor: pointer;
}
.ctools-button-processed .ctools-content {
padding-bottom: 2px;
padding-top: 2px;
}
.ctools-no-js .ctools-content ul,
.ctools-button-processed .ctools-content ul {
list-style-image: none;
list-style-type: none;
}
.ctools-button-processed li {
line-height: 1.3333;
}
.ctools-button li a {
padding-left: 12px;
padding-right: 12px;
}
.ctools-collapsible-container .ctools-toggle {
float: left;
width: 21px;
height: 21px;
cursor: pointer;
background-position: 7px 7px;
background-repeat: no-repeat;
background-image: url(../images/collapsible-expanded.png);
}
.ctools-collapsible-container .ctools-collapsible-handle {
display: none;
}
html.js .ctools-collapsible-container .ctools-collapsible-handle {
display: block;
}
.ctools-collapsible-container .ctools-collapsible-handle {
cursor: pointer;
}
.ctools-collapsible-container .ctools-toggle-collapsed {
background-image: url(../images/collapsible-collapsed.png);
}
.ctools-context-holder .ctools-context-title {
float: left;
width: 49%;
font-style: italic;
}
.ctools-context-holder .ctools-context-content {
float: right;
width: 49%;
}
.ctools-locked {
color: red;
border: 1px solid red;
padding: 1em;
}
.ctools-owns-lock {
background: #FFFFDD none repeat scroll 0 0;
border: 1px solid #F0C020;
padding: 1em;
}
a.ctools-ajaxing,
input.ctools-ajaxing,
button.ctools-ajaxing,
select.ctools-ajaxing {
padding-right: 18px !important;
background: url(../images/status-active.gif) right center no-repeat;
}
div.ctools-ajaxing {
float: left;
width: 18px;
background: url(../images/status-active.gif) center center no-repeat;
}
.ctools-dropbutton-processed {
padding-right: 18px;
position: relative;
background-color: inherit;
}
.ctools-dropbutton-processed.open {
z-index: 200;
}
.ctools-dropbutton-processed .ctools-content li,
.ctools-dropbutton-processed .ctools-content a {
display: block;
}
.ctools-dropbutton-processed .ctools-link {
bottom: 0;
display: block;
height: auto;
position: absolute;
right: 0;
text-indent: -9999px; /* LTR */
top: 0;
width: 17px;
}
.ctools-dropbutton-processed .ctools-link a {
overflow: hidden;
}
.ctools-dropbutton-processed .ctools-content ul {
margin: 0;
overflow: hidden;
}
.ctools-dropbutton-processed.open li + li {
padding-top: 4px;
}
/**
* This creates the dropbutton arrow and inherits the link color
*/
.ctools-twisty {
border-bottom-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
border-style: solid;
border-width: 4px 4px 0;
line-height: 0;
right: 6px;
position: absolute;
top: 0.75em;
}
.ctools-dropbutton-processed.open .ctools-twisty {
border-bottom: 4px solid;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: transparent;
top: 0.5em;
}
.ctools-no-js .ctools-twisty {
display: none;
}
html.js div.ctools-dropdown div.ctools-dropdown-container {
z-index: 1001;
display: none;
text-align: left;
position: absolute;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul li a {
display: block;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul {
list-style-type: none;
margin: 0;
padding: 0;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul li {
display: block;
/* prevent excess right margin in IE */
margin-right: 0;
margin-left: 0;
padding-right: 0;
padding-left: 0;
background-image: none; /* prevent list backgrounds from mucking things up */
}
.ctools-dropdown-no-js .ctools-dropdown-link,
.ctools-dropdown-no-js span.text {
display: none;
}
/* Everything from here down is purely visual style and can be overridden. */
html.js div.ctools-dropdown a.ctools-dropdown-text-link {
background: url(../images/collapsible-expanded.png) 3px 5px no-repeat;
padding-left: 12px;
}
html.js div.ctools-dropdown div.ctools-dropdown-container {
width: 175px;
background: #fff;
border: 1px solid black;
margin: 4px 1px 0 0;
padding: 0;
color: #494949;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul li li a {
padding-left: 25px;
width: 150px;
color: #027AC6;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul li a {
text-decoration: none;
padding-left: 5px;
width: 170px;
color: #027AC6;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul li span {
display: block;
}
html.js div.ctools-dropdown div.ctools-dropdown-container ul li span.text {
font-style: italic;
padding-left: 5px;
}
html.js .ctools-dropdown-hover {
background-color: #ECECEC;
}
body form#ctools-export-ui-list-form {
margin: 0 0 20px 0;
}
#ctools-export-ui-list-form .form-item {
padding-right: 1em; /* LTR */
float: left; /* LTR */
margin-top: 0;
margin-bottom: 0;
}
#ctools-export-ui-list-items {
width: 100%;
}
#edit-order-wrapper {
clear: left; /* LTR */
}
#ctools-export-ui-list-form .form-submit {
margin-top: 1.65em;
float: left; /* LTR */
}
tr.ctools-export-ui-disabled td {
color: #999;
}
th.ctools-export-ui-operations,
td.ctools-export-ui-operations {
text-align: right; /* LTR */
vertical-align: top;
}
/* Force the background color to inherit so that the dropbuttons do not need
a specific background color. */
td.ctools-export-ui-operations {
background-color: inherit;
}
td.ctools-export-ui-operations .ctools-dropbutton {
text-align: left; /* LTR */
position: absolute;
right: 10px;
}
div.ctools-modal-content {
background: #fff;
color: #000;
padding: 0;
margin: 2px;
border: 1px solid #000;
width: 600px;
text-align: left;
}
div.ctools-modal-content .modal-title {
font-size: 120%;
font-weight: bold;
color: white;
overflow: hidden;
white-space: nowrap;
}
div.ctools-modal-content .modal-header {
background-color: #2385c2;
padding: 0 .25em 0 1em;
}
div.ctools-modal-content .modal-header a {
color: white;
}
div.ctools-modal-content .modal-content {
padding: 1em 1em 0 1em;
overflow: auto;
position: relative; /* Keeps IE7 from flowing outside the modal. */
}
div.ctools-modal-content .modal-form {
}
div.ctools-modal-content a.close {
color: white;
float: right;
}
div.ctools-modal-content a.close:hover {
text-decoration: none;
}
div.ctools-modal-content a.close img {
position: relative;
top: 1px;
}
div.ctools-modal-content .modal-content .modal-throbber-wrapper {
text-align: center;
}
div.ctools-modal-content .modal-content .modal-throbber-wrapper img {
margin-top: 160px;
}
/** modal forms CSS **/
div.ctools-modal-content .form-item label {
width: 15em;
float: left;
}
div.ctools-modal-content .form-item label.option {
width: auto;
float: none;
}
div.ctools-modal-content .form-item .description {
clear: left;
}
div.ctools-modal-content .form-item .description .tips {
margin-left: 2em;
}
div.ctools-modal-content .no-float .form-item * {
float: none;
}
div.ctools-modal-content .modal-form .no-float label {
width: auto;
}
div.ctools-modal-content fieldset,
div.ctools-modal-content .form-radios,
div.ctools-modal-content .form-checkboxes {
clear: left;
}
div.ctools-modal-content .resizable-textarea {
width: auto;
margin-left: 15em;
margin-right: 5em;
}
div.ctools-modal-content .container-inline .form-item {
margin-right: 2em;
}
#views-exposed-pane-wrapper .form-item {
margin-top: 0;
margin-bottom: 0;
}
div.ctools-modal-content label.hidden-options {
background: transparent url(../images/arrow-active.png) no-repeat right;
height: 12px;
padding-right: 12px;
}
div.ctools-modal-content label.expanded-options {
background: transparent url(../images/expanded-options.png) no-repeat right;
height: 12px;
padding-right: 16px;
}
div.ctools-modal-content .option-text-aligner label.expanded-options,
div.ctools-modal-content .option-text-aligner label.hidden-options {
background: none;
}
div.ctools-modal-content .dependent-options {
padding-left: 30px;
}
.ctools-right-container {
float: right;
padding: 0 0 0 .5em;
margin: 0;
width: 48.5%;
}
.ctools-left-container {
padding-right: .5em;
width: 48.5%;
}
/* Farbtastic placement */
.color-form {
max-width: 50em;
position: relative;
min-height: 195px;
}
#placeholder {
/*
position: absolute;
top: 0;
right: 0;
*/
margin: 0 auto;
width: 195px;
}
/* Palette */
.color-form .form-item {
height: 2em;
line-height: 2em;
padding-left: 1em; /* LTR */
margin: 0.5em 0;
}
.color-form .form-item input {
margin-top: .2em;
}
.color-form label {
float: left; /* LTR */
clear: left; /* LTR */
width: 14em;
}
.color-form .form-text, .color-form .form-select {
float: left; /* LTR */
}
.color-form .form-text {
text-align: center;
margin-right: 5px; /* LTR */
cursor: pointer;
}
#palette .hook {
float: left; /* LTR */
margin-top: 3px;
width: 16px;
height: 16px;
}
#palette .up {
background-position: 100% -27px; /* LTR */
}
#palette .both {
background-position: 100% -54px; /* LTR */
}
#palette .form-item {
width: 24em;
}
#palette .item-selected {
background: #eee;
}
/* Preview */
#preview {
width: 45%;
float: right;
margin: 0;
}
#ctools_stylizer_color_scheme_form {
float: left;
width: 45%;
margin: 0;
}
/* general style for the layout-icon */
.ctools-style-icon .caption {
width: 100px;
margin-bottom: 1em;
line-height: 1em;
text-align: center;
cursor: default;
}
.ctools-style-icons .form-item {
width: 100px;
float: left;
margin: 0 3px !important;
}
.ctools-style-icons .form-item .ctools-style-icon {
float: none;
height: 150px;
width: 100px;
}
.ctools-style-icons .form-item label.option {
width: 100px;
display: block;
text-align: center;
}
.ctools-style-icons .form-item label.option input {
margin: 0 auto;
}
.ctools-style-icons .ctools-style-category {
height: 190px;
}
.ctools-style-icons .ctools-style-category label {
font-weight: bold;
width: 100%;
float: left;
}
/**
* Stylizer font editor widget
*/
.ctools-stylizer-spacing-form .form-item {
float: left;
margin: .25em;
}
#edit-font-font {
width: 9em;
}
.wizard-trail {
font-size: 120%;
}
.wizard-trail-current {
font-weight: bold;
}
<?php
/**
* @file
* Hooks provided by the Chaos Tool Suite.
*
* This file is divided into static hooks (hooks with string literal names) and
* dynamic hooks (hooks with pattern-derived string names).
*/
/**
* @addtogroup hooks
* @{
*/
/**
* Inform CTools about plugin types.
*
* @return array
* An array of plugin types, keyed by the type name.
* See the advanced help topic 'plugins-creating' for details of the array
* properties.
*/
function hook_ctools_plugin_type() {
$plugins['my_type'] = array(
'load themes' => TRUE,
);
return $plugins;
}
/**
* This hook is used to inform the CTools plugin system about the location of a
* directory that should be searched for files containing plugins of a
* particular type. CTools invokes this same hook for all plugins, using the
* two passed parameters to indicate the specific type of plugin for which it
* is searching.
*
* The $plugin_type parameter is self-explanatory - it is the string name of the
* plugin type (e.g., Panels' 'layouts' or 'styles'). The $owner parameter is
* necessary because CTools internally namespaces plugins by the module that
* owns them. This is an extension of Drupal best practices on avoiding global
* namespace pollution by prepending your module name to all its functions.
* Consequently, it is possible for two different modules to create a plugin
* type with exactly the same name and have them operate in harmony. In fact,
* this system renders it impossible for modules to encroach on other modules'
* plugin namespaces.
*
* Given this namespacing, it is important that implementations of this hook
* check BOTH the $owner and $plugin_type parameters before returning a path.
* If your module does not implement plugins for the requested module/plugin
* combination, it is safe to return nothing at all (or NULL). As a convenience,
* it is also safe to return a path that does not exist for plugins your module
* does not implement - see form 2 for a use case.
*
* Note that modules implementing a plugin also must implement this hook to
* instruct CTools as to the location of the plugins. See form 3 for a use case.
*
* The conventional structure to return is "plugins/$plugin_type" - that is, a
* 'plugins' subdirectory in your main module directory, with individual
* directories contained therein named for the plugin type they contain.
*
* @param string $owner
* The system name of the module owning the plugin type for which a base
* directory location is being requested.
* @param string $plugin_type
* The name of the plugin type for which a base directory is being requested.
* @return string
* The path where CTools' plugin system should search for plugin files,
* relative to your module's root. Omit leading and trailing slashes.
*/
function hook_ctools_plugin_directory($owner, $plugin_type) {
// Form 1 - for a module implementing only the 'content_types' plugin owned
// by CTools, this would cause the plugin system to search the
// <moduleroot>/plugins/content_types directory for .inc plugin files.
if ($owner == 'ctools' && $plugin_type == 'content_types') {
return 'plugins/content_types';
}
// Form 2 - if your module implements only Panels plugins, and has 'layouts'
// and 'styles' plugins but no 'cache' or 'display_renderers', it is OK to be
// lazy and return a directory for a plugin you don't actually implement (so
// long as that directory doesn't exist). This lets you avoid ugly in_array()
// logic in your conditional, and also makes it easy to add plugins of those
// types later without having to change this hook implementation.
if ($owner == 'panels') {
return "plugins/$plugin_type";
}
// Form 3 - CTools makes no assumptions about where your plugins are located,
// so you still have to implement this hook even for plugins created by your
// own module.
if ($owner == 'mymodule') {
// Yes, this is exactly like Form 2 - just a different reasoning for it.
return "plugins/$plugin_type";
}
// Finally, if nothing matches, it's safe to return nothing at all (or NULL).
}
/**
* Alter a plugin before it has been processed.
*
* This hook is useful for altering flags or other information that will be
* used or possibly overriden by the process hook if defined.
*
* @param $plugin
* An associative array defining a plugin.
* @param $info
* An associative array of plugin type info.
*/
function hook_ctools_plugin_pre_alter(&$plugin, &$info) {
// Override a function defined by the plugin.
if ($info['type'] == 'my_type') {
$plugin['my_flag'] = 'new_value';
}
}
/**
* Alter a plugin after it has been processed.
*
* This hook is useful for overriding the final values for a plugin after it
* has been processed.
*
* @param $plugin
* An associative array defining a plugin.
* @param $info
* An associative array of plugin type info.
*/
function hook_ctools_plugin_post_alter(&$plugin, &$info) {
// Override a function defined by the plugin.
if ($info['type'] == 'my_type') {
$plugin['my_function'] = 'new_function';
}
}
/**
* Alter the list of modules/themes which implement a certain api.
*
* The hook named here is just an example, as the real existing hooks are named
* for example 'hook_views_api_alter'.
*
* @param array $list
* An array of informations about the implementors of a certain api.
* The key of this array are the module names/theme names.
*/
function hook_ctools_api_hook_alter(&$list) {
// Alter the path of the node implementation.
$list['node']['path'] = drupal_get_path('module', 'node');
}
/**
* Alter the available functions to be used in ctools math expression api.
*
* One usecase would be to create your own function in your module and
* allow to use it in the math expression api.
*
* @param $functions
* An array which has the functions as value.
*/
function hook_ctools_math_expression_functions_alter(&$functions) {
// Allow to convert from degrees to radiant.
$functions[] = 'deg2rad';
}
/**
* Alter everything.
*
* @param $info
* An associative array containing the following keys:
* - content: The rendered content.
* - title: The content's title.
* - no_blocks: A boolean to decide if blocks should be displayed.
* @param $page
* If TRUE then this renderer owns the page and can use theme('page')
* for no blocks; if false, output is returned regardless of any no
* blocks settings.
* @param $context
* An associative array containing the following keys:
* - args: The raw arguments behind the contexts.
* - contexts: The context objects in use.
* - task: The task object in use.
* - subtask: The subtask object in use.
* - handler: The handler object in use.
*/
function hook_ctools_render_alter(&$info, &$page, &$context) {
if ($context['handler']->name == 'my_handler') {
ctools_add_css('my_module.theme', 'my_module');
}
}
/**
* Alter a content plugin subtype.
*
* While content types can be altered via hook_ctools_plugin_pre_alter() or
* hook_ctools_plugin_post_alter(), the subtypes that content types rely on
* are special and require their own hook.
*
* This hook can be used to add things like 'render last' or change icons
* or categories or to rename content on specific sites.
*/
function hook_ctools_content_subtype_alter($subtype, $plugin) {
$subtype['render last'] = TRUE;
}
/**
* Alter the definition of an entity context plugin.
*
* @param array $plugin
* An associative array defining a plugin.
* @param array $entity
* The entity info array of a specific entity type.
* @param string $plugin_id
* The plugin ID, in the format NAME:KEY.
*/
function hook_ctools_entity_context_alter(&$plugin, &$entity, $plugin_id) {
ctools_include('context');
switch ($plugin_id) {
case 'entity_id:taxonomy_term':
$plugin['no ui'] = TRUE;
case 'entity:user':
$plugin = ctools_get_context('user');
unset($plugin['no ui']);
unset($plugin['no required context ui']);
break;
}
}
/**
* Alter the definition of entity context plugins.
*
* @param array $plugins
* An associative array of plugin definitions, keyed by plugin ID.
*
* @see hook_ctools_entity_context_alter()
*/
function hook_ctools_entity_contexts_alter(&$plugins) {
$plugins['entity_id:taxonomy_term']['no ui'] = TRUE;
}
/**
* Change cleanstring settings.
*
* @param array $settings
* An associative array of cleanstring settings.
*
* @see ctools_cleanstring()
*/
function hook_ctools_cleanstring_alter(&$settings) {
// Convert all strings to lower case.
$settings['lower case'] = TRUE;
}
/**
* Change cleanstring settings for a specific clean ID.
*
* @param array $settings
* An associative array of cleanstring settings.
*
* @see ctools_cleanstring()
*/
function hook_ctools_cleanstring_CLEAN_ID_alter(&$settings) {
// Convert all strings to lower case.
$settings['lower case'] = TRUE;
}
/**
* @} End of "addtogroup hooks".
*/
name = Chaos tools
description = A library of helpful tools by Merlin of Chaos.
core = 7.x
package = Chaos tool suite
files[] = includes/context.inc
files[] = includes/math-expr.inc
files[] = includes/stylizer.inc
; Information added by drupal.org packaging script on 2013-04-03
version = "7.x-1.3"
core = "7.x"
project = "ctools"
datestamp = "1365013512"
<?php
/**
* @file
* Contains install and update functions for ctools.
*/
/**
* Use requirements to ensure that the CTools CSS cache directory can be
* created and that the PHP version requirement is met.
*/
function ctools_requirements($phase) {
$requirements = array();
if ($phase == 'runtime') {
$requirements['ctools_css_cache'] = array(
'title' => t('CTools CSS Cache'),
'severity' => REQUIREMENT_OK,
'value' => t('Exists'),
);
$path = 'public://ctools/css';
if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
$requirements['ctools_css_cache']['description'] = t('The CTools CSS cache directory, %path could not be created due to a misconfigured files directory. Please ensure that the files directory is correctly configured and that the webserver has permission to create directories.', array('%path' => file_uri_target($path)));
$requirements['ctools_css_cache']['severity'] = REQUIREMENT_ERROR;
$requirements['ctools_css_cache']['value'] = t('Unable to create');
}
if (!function_exists('error_get_last')) {
$requirements['ctools_php_52']['title'] = t('CTools PHP requirements');
$requirements['ctools_php_52']['description'] = t('CTools requires certain features only available in PHP 5.2.0 or higher.');
$requirements['ctools_php_52']['severity'] = REQUIREMENT_WARNING;
$requirements['ctools_php_52']['value'] = t('PHP !version', array('!version' => phpversion()));
}
}
return $requirements;
}
/**
* Implements hook_schemea
*/
function ctools_schema() {
return ctools_schema_2();
}
/**
* Version 2 of the CTools schema.
*/
function ctools_schema_2() {
$schema = ctools_schema_1();
// update the 'name' field to be 128 bytes long:
$schema['ctools_object_cache']['fields']['name']['length'] = 128;
// Update the 'data' field to be type 'blob'.
$schema['ctools_object_cache']['fields']['data'] = array(
'type' => 'blob',
'size' => 'big',
'description' => 'Serialized data being stored.',
'serialize' => TRUE,
);
// DO NOT MODIFY THIS TABLE -- this definition is used to create the table.
// Changes to this table must be made in schema_3 or higher.
$schema['ctools_css_cache'] = array(
'description' => 'A special cache used to store CSS that must be non-volatile.',
'fields' => array(
'cid' => array(
'type' => 'varchar',
'length' => '128',
'description' => 'The CSS ID this cache object belongs to.',
'not null' => TRUE,
),
'filename' => array(
'type' => 'varchar',
'length' => '255',
'description' => 'The filename this CSS is stored in.',
),
'css' => array(
'type' => 'text',
'size' => 'big',
'description' => 'CSS being stored.',
'serialize' => TRUE,
),
'filter' => array(
'type' => 'int',
'size' => 'tiny',
'description' => 'Whether or not this CSS needs to be filtered.',
),
),
'primary key' => array('cid'),
);
return $schema;
}
/**
* CTools' initial schema; separated for the purposes of updates.
*
* DO NOT MAKE CHANGES HERE. This schema version is locked.
*/
function ctools_schema_1() {
$schema['ctools_object_cache'] = array(
'description' => t('A special cache used to store objects that are being edited; it serves to save state in an ordinarily stateless environment.'),
'fields' => array(
'sid' => array(
'type' => 'varchar',
'length' => '64',
'not null' => TRUE,
'description' => 'The session ID this cache object belongs to.',
),
'name' => array(
'type' => 'varchar',
'length' => '32',
'not null' => TRUE,
'description' => 'The name of the object this cache is attached to.',
),
'obj' => array(
'type' => 'varchar',
'length' => '32',
'not null' => TRUE,
'description' => 'The type of the object this cache is attached to; this essentially represents the owner so that several sub-systems can use this cache.',
),
'updated' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The time this cache was created or updated.',
),
'data' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Serialized data being stored.',
'serialize' => TRUE,
),
),
'primary key' => array('sid', 'obj', 'name'),
'indexes' => array('updated' => array('updated')),
);
return $schema;
}
/**
* Enlarge the ctools_object_cache.name column to prevent truncation and weird
* errors.
*/
function ctools_update_6001() {
// Perform updates like this to reduce code duplication.
$schema = ctools_schema_2();
db_change_field('ctools_object_cache', 'name', 'name', $schema['ctools_object_cache']['fields']['name']);
}
/**
* Add the new css cache table.
*/
function ctools_update_6002() {
// Schema 2 is locked and should not be changed.
$schema = ctools_schema_2();
db_create_table('ctools_css_cache', $schema['ctools_css_cache']);
}
/**
* Take over for the panels_views module if it was on.
*/
function ctools_update_6003() {
$result = db_query('SELECT status FROM {system} WHERE name = :name', array(':name' => 'panels_views'))->fetchField();
if ($result) {
db_delete('system')->condition('name', 'panels_views')->execute();
module_enable(array('views_content'), TRUE);
}
}
/**
* Add primary key to the ctools_object_cache table.
*/
function ctools_update_6004() {
db_add_primary_key('ctools_object_cache', array('sid', 'obj', 'name'));
db_drop_index('ctools_object_cache', 'sid_obj_name');
}
/**
* Removed update.
*/
function ctools_update_6005() {
return array();
}
/**
* ctools_custom_content table was originally here, but is now moved to
* its own module.
*/
function ctools_update_6007() {
$ret = array();
if (db_table_exists('ctools_custom_content')) {
// Enable the module to make everything as seamless as possible.
module_enable(array('ctools_custom_content'), TRUE);
}
return $ret;
}
/**
* ctools_object_cache needs to be defined as a blob.
*/
function ctools_update_6008() {
db_delete('ctools_object_cache')
->execute();
db_change_field('ctools_object_cache', 'data', 'data', array(
'type' => 'blob',
'size' => 'big',
'description' => 'Serialized data being stored.',
'serialize' => TRUE,
)
);
}
This diff is collapsed.
name = Custom rulesets
description = Create custom, exportable, reusable access rulesets for applications like Panels.
core = 7.x
package = Chaos tool suite
dependencies[] = ctools
; Information added by drupal.org packaging script on 2013-04-03
version = "7.x-1.3"
core = "7.x"
project = "ctools"
datestamp = "1365013512"
<?php
/**
* Schema for customizable access rulesets.
*/
function ctools_access_ruleset_schema() {
return ctools_access_ruleset_schema_1();
}
function ctools_access_ruleset_schema_1() {
$schema = array();
$schema['ctools_access_ruleset'] = array(
'description' => 'Contains exportable customized access rulesets.',
'export' => array(
'identifier' => 'ruleset',
'bulk export' => TRUE,
'primary key' => 'rsid',
'api' => array(
'owner' => 'ctools_access_ruleset',
'api' => 'ctools_rulesets',
'minimum_version' => 1,
'current_version' => 1,
),
),
'fields' => array(
'rsid' => array(
'type' => 'serial',
'description' => 'A database primary key to ensure uniqueness',
'not null' => TRUE,
'no export' => TRUE,
),
'name' => array(
'type' => 'varchar',
'length' => '255',
'description' => 'Unique ID for this ruleset. Used to identify it programmatically.',
),
'admin_title' => array(
'type' => 'varchar',
'length' => '255',
'description' => 'Administrative title for this ruleset.',
),
'admin_description' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Administrative description for this ruleset.',
'object default' => '',
),
'requiredcontexts' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Any required contexts for this ruleset.',
'serialize' => TRUE,
'object default' => array(),
),
'contexts' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Any embedded contexts for this ruleset.',
'serialize' => TRUE,
'object default' => array(),
),
'relationships' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Any relationships for this ruleset.',
'serialize' => TRUE,
'object default' => array(),
),
'access' => array(
'type' => 'text',
'size' => 'big',
'description' => 'The actual group of access plugins for this ruleset.',
'serialize' => TRUE,
'object default' => array(),
),
),
'primary key' => array('rsid'),
);
return $schema;
}
<?php
/**
* @file
* ctools_access_ruleset module
*
* This module allows styles to be created and managed on behalf of modules
* that implement styles.
*
* The ctools_access_ruleset tool allows recolorable styles to be created via a miniature
* scripting language. Panels utilizes this to allow administrators to add
* styles directly to any panel display.
*/
/**
* Implementation of hook_permission()
*/
function ctools_access_ruleset_permission() {
return array(
'administer ctools access ruleset' => array(
'title' => t('Administer access rulesets'),
'description' => t('Add, delete and edit custom access rulesets.'),
),
);
}
/**
* Implementation of hook_ctools_plugin_directory() to let the system know
* we implement task and task_handler plugins.
*/
function ctools_access_ruleset_ctools_plugin_directory($module, $plugin) {
// Most of this module is implemented as an export ui plugin, and the
// rest is in ctools/includes/ctools_access_ruleset.inc
if ($module == 'ctools' && ($plugin == 'export_ui' || $plugin == 'access')) {
return 'plugins/' . $plugin;
}
}
/**
* Implementation of hook_panels_dashboard_blocks().
*
* Adds page information to the Panels dashboard.
*/
function ctools_access_ruleset_panels_dashboard_blocks(&$vars) {
$vars['links']['ctools_access_ruleset'] = array(
'title' => l(t('Custom ruleset'), 'admin/structure/ctools-rulesets/add'),
'description' => t('Custom rulesets are combinations of access plugins you can use for access control, selection criteria and pane visibility.'),
);
// Load all mini panels and their displays.
ctools_include('export');
$items = ctools_export_crud_load_all('ctools_access_ruleset');
$count = 0;
$rows = array();
foreach ($items as $item) {
$rows[] = array(
check_plain($item->admin_title),
array(
'data' => l(t('Edit'), "admin/structure/ctools-rulesets/list/$item->name/edit"),
'class' => 'links',
),
);
// Only show 10.
if (++$count >= 10) {
break;
}
}
if ($rows) {
$content = theme('table', array('rows' => $rows, 'attributes' => array('class' => 'panels-manage')));
}
else {
$content = '<p>' . t('There are no custom rulesets.') . '</p>';
}
$vars['blocks']['ctools_access_ruleset'] = array(
'title' => t('Manage custom rulesets'),
'link' => l(t('Go to list'), 'admin/structure/ctools-rulesets'),
'content' => $content,
'class' => 'dashboard-ruleset',
'section' => 'right',
);
}
<?php
/**
* @file
* Plugin to provide access control based on user rulesetission strings.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => '',
'description' => '',
'callback' => 'ctools_ruleset_ctools_access_check',
'settings form' => 'ctools_ruleset_ctools_access_settings',
'summary' => 'ctools_ruleset_ctools_access_summary',
// This access plugin actually just contains child plugins that are
// exportable, UI configured rulesets.
'get child' => 'ctools_ruleset_ctools_access_get_child',
'get children' => 'ctools_ruleset_ctools_access_get_children',
);
/**
* Merge the main access plugin with a loaded ruleset to form a child plugin.
*/
function ctools_ruleset_ctools_access_merge_plugin($plugin, $parent, $item) {
$plugin['name'] = $parent . ':' . $item->name;
$plugin['title'] = check_plain($item->admin_title);
$plugin['description'] = check_plain($item->admin_description);
// TODO: Generalize this in CTools.
if (!empty($item->requiredcontexts)) {
$plugin['required context'] = array();
foreach ($item->requiredcontexts as $context) {
$info = ctools_get_context($context['name']);
// TODO: allow an optional setting
$plugin['required context'][] = new ctools_context_required($context['identifier'], $info['context name']);
}
}
// Store the loaded ruleset in the plugin.
$plugin['ruleset'] = $item;
return $plugin;
}
/**
* Get a single child access plugin.
*/
function ctools_ruleset_ctools_access_get_child($plugin, $parent, $child) {
ctools_include('export');
$item = ctools_export_crud_load('ctools_access_ruleset', $child);
if ($item) {
return ctools_ruleset_ctools_access_merge_plugin($plugin, $parent, $item);
}
}
/**
* Get all child access plugins.
*/
function ctools_ruleset_ctools_access_get_children($plugin, $parent) {
$plugins = array();
ctools_include('export');
$items = ctools_export_crud_load_all('ctools_access_ruleset');
foreach ($items as $name => $item) {
$child = ctools_ruleset_ctools_access_merge_plugin($plugin, $parent, $item);
$plugins[$child['name']] = $child;
}
return $plugins;
}
/**
* Settings form for the 'by ruleset' access plugin
*/
function ctools_ruleset_ctools_access_settings(&$form, &$form_state, $conf) {
if (!empty($form_state['plugin']['ruleset']->admin_description)) {
$form['markup'] = array(
'#markup' => '<div class="description">' . check_plain($form_state['plugin']['ruleset']->admin_description) . '</div>',
);
}
return $form;
}
/**
* Check for access.
*/
function ctools_ruleset_ctools_access_check($conf, $context, $plugin) {
// Load up any contexts we might be using.
$contexts = ctools_context_match_required_contexts($plugin['ruleset']->requiredcontexts, $context);
$contexts = ctools_context_load_contexts($plugin['ruleset'], FALSE, $contexts);
return ctools_access($plugin['ruleset']->access, $contexts);
}
/**
* Provide a summary description based upon the checked roles.
*/
function ctools_ruleset_ctools_access_summary($conf, $context, $plugin) {
if (!empty($plugin['ruleset']->admin_description)) {
return check_plain($plugin['ruleset']->admin_description);
}
else {
return check_plain($plugin['ruleset']->admin_title);
}
}
<?php
$plugin = array(
'schema' => 'ctools_access_ruleset',
'access' => 'administer ctools access ruleset',
'menu' => array(
'menu item' => 'ctools-rulesets',
'menu title' => 'Custom access rulesets',
'menu description' => 'Add, edit or delete custom access rulesets for use with Panels and other systems that utilize CTools content plugins.',
),
'title singular' => t('ruleset'),
'title singular proper' => t('Ruleset'),
'title plural' => t('rulesets'),
'title plural proper' => t('Rulesets'),
'handler' => 'ctools_access_ruleset_ui',
'use wizard' => TRUE,
'form info' => array(
'order' => array(
'basic' => t('Basic information'),
'context' => t('Contexts'),
'rules' => t('Rules'),
),
),
);
<?php
class ctools_access_ruleset_ui extends ctools_export_ui {
function edit_form_context(&$form, &$form_state) {
ctools_include('context-admin');
ctools_context_admin_includes();
ctools_add_css('ruleset');
$form['right'] = array(
'#prefix' => '<div class="ctools-right-container">',
'#suffix' => '</div>',
);
$form['left'] = array(
'#prefix' => '<div class="ctools-left-container clearfix">',
'#suffix' => '</div>',
);
// Set this up and we can use CTools' Export UI's built in wizard caching,
// which already has callbacks for the context cache under this name.
$module = 'export_ui::' . $this->plugin['name'];
$name = $this->edit_cache_get_key($form_state['item'], $form_state['form type']);
ctools_context_add_context_form($module, $form, $form_state, $form['right']['contexts_table'], $form_state['item'], $name);
ctools_context_add_required_context_form($module, $form, $form_state, $form['left']['required_contexts_table'], $form_state['item'], $name);
ctools_context_add_relationship_form($module, $form, $form_state, $form['right']['relationships_table'], $form_state['item'], $name);
}
function edit_form_rules(&$form, &$form_state) {
// The 'access' UI passes everything via $form_state, unlike the 'context' UI.
// The main difference is that one is about 3 years newer than the other.
ctools_include('context');
ctools_include('context-access-admin');
$form_state['access'] = $form_state['item']->access;
$form_state['contexts'] = ctools_context_load_contexts($form_state['item']);
$form_state['module'] = 'ctools_export_ui';
$form_state['callback argument'] = $form_state['object']->plugin['name'] . ':' . $form_state['object']->edit_cache_get_key($form_state['item'], $form_state['form type']);
$form_state['no buttons'] = TRUE;
$form = ctools_access_admin_form($form, $form_state);
}
function edit_form_rules_submit(&$form, &$form_state) {
$form_state['item']->access['logic'] = $form_state['values']['logic'];
}
function edit_form_submit(&$form, &$form_state) {
parent::edit_form_submit($form, $form_state);
}
}
div.ctools-sample-modal-content {
background:none;
border:0;
color:#000000;
margin:0;
padding:0;
text-align:left;
}
div.ctools-sample-modal-content .modal-scroll{
overflow:hidden;
overflow-y:auto;
}
div.ctools-sample-modal-content #popups-overlay {
background-color:transparent;
}
div.ctools-sample-modal-content #popups-loading {
width:248px;
position:absolute;
display:none;
opacity:1;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
z-index:99;
}
div.ctools-sample-modal-content #popups-loading span.popups-loading-message {
background:#FFF url(../images/loading-large.gif) no-repeat 8px center;
display:block;
color:#444444;
font-family:Arial;
font-size:22px;
font-weight:bold;
height:36px;
line-height:36px;
padding:0 40px;
}
div.ctools-sample-modal-content #popups-loading table,
div.ctools-sample-modal-content .popups-box table {
margin:0px;
}
div.ctools-sample-modal-content #popups-loading tbody,
div.ctools-sample-modal-content .popups-box tbody {
border:none;
}
div.ctools-sample-modal-content .popups-box tr {
background-color:transparent;
}
div.ctools-sample-modal-content td.popups-border {
background: url(../images/popups-border.png);
background-color:transparent;
border: none;
}
div.ctools-sample-modal-content td.popups-tl,
div.ctools-sample-modal-content td.popups-tr,
div.ctools-sample-modal-content td.popups-bl,
div.ctools-sample-modal-content td.popups-br {
background-repeat: no-repeat;
height:10px;
padding:0px;
}
div.ctools-sample-modal-content td.popups-tl { background-position: 0px 0px; }
div.ctools-sample-modal-content td.popups-t,
div.ctools-sample-modal-content td.popups-b {
background-position: 0px -40px;
background-repeat: repeat-x;
}
div.ctools-sample-modal-content td.popups-tr { background-position: 0px -10px; width: 10px; }
div.ctools-sample-modal-content td.popups-cl,
div.ctools-sample-modal-content td.popups-cr {
background-position: -10px 0;
background-repeat: repeat-y;
width:10px;
}
div.ctools-sample-modal-content td.popups-cl,
div.ctools-sample-modal-content td.popups-cr,
div.ctools-sample-modal-content td.popups-c { padding:0; border: none; }
div.ctools-sample-modal-content td.popups-c { background:#fff; }
div.ctools-sample-modal-content td.popups-bl { background-position: 0px -20px; }
div.ctools-sample-modal-content td.popups-br { background-position: 0px -30px; width: 10px; }
div.ctools-sample-modal-content .popups-box,
div.ctools-sample-modal-content #popups-loading {
border: 0px solid #454545;
opacity:1;
overflow:hidden;
padding:0;
background-color:transparent;
}
div.ctools-sample-modal-content .popups-container {
overflow:hidden;
height:100%;
background-color:#fff;
}
div.ctools-sample-modal-content div.popups-title {
-moz-border-radius-topleft: 0px;
-webkit-border-radius-topleft: 0px;
margin-bottom:0px;
background-color:#ff7200;
border:1px solid #ce5c00;
padding:4px 10px 5px;
color:white;
font-size:1em;
font-weight:bold;
}
div.ctools-sample-modal-content .popups-body {
background-color:#fff;
padding:8px;
}
div.ctools-sample-modal-content .popups-box .popups-buttons,
div.ctools-sample-modal-content .popups-box .popups-footer {
background-color:#fff;
}
div.ctools-sample-modal-content .popups-title a.close {
color: #fff;
text-decoration:none;
}
div.ctools-sample-modal-content .popups-close {
font-size:120%;
float:right;
text-align:right;
}
div.ctools-sample-modal-content .modal-loading-wrapper {
width:220px;
height:19px;
margin:0 auto;
margin-top:2%;
}
div.ctools-sample-modal-content tbody{
border:none;
}
div.ctools-sample-modal-content .modal-content .modal-throbber-wrapper img {
margin-top: 100px;
}
name = Chaos Tools (CTools) AJAX Example
description = Shows how to use the power of Chaos AJAX.
package = Chaos tool suite
dependencies[] = ctools
core = 7.x
; Information added by drupal.org packaging script on 2013-04-03
version = "7.x-1.3"
core = "7.x"
project = "ctools"
datestamp = "1365013512"
<?php
/**
* @file
*/
/**
* Implementation of hook_install()
*/
function ctools_ajax_sample_install() {
}
/**
* Implementation of hook_uninstall()
*/
function ctools_ajax_sample_uninstall() {
}
/**
* Provide the HTML to create the modal dialog.
*/
Drupal.theme.prototype.CToolsSampleModal = function () {
var html = '';
html += '<div id="ctools-modal" class="popups-box">';
html += ' <div class="ctools-modal-content ctools-sample-modal-content">';
html += ' <table cellpadding="0" cellspacing="0" id="ctools-face-table">';
html += ' <tr>';
html += ' <td class="popups-tl popups-border"></td>';
html += ' <td class="popups-t popups-border"></td>';
html += ' <td class="popups-tr popups-border"></td>';
html += ' </tr>';
html += ' <tr>';
html += ' <td class="popups-cl popups-border"></td>';
html += ' <td class="popups-c" valign="top">';
html += ' <div class="popups-container">';
html += ' <div class="modal-header popups-title">';
html += ' <span id="modal-title" class="modal-title"></span>';
html += ' <span class="popups-close"><a class="close" href="#">' + Drupal.CTools.Modal.currentSettings.closeText + '</a></span>';
html += ' <div class="clear-block"></div>';
html += ' </div>';
html += ' <div class="modal-scroll"><div id="modal-content" class="modal-content popups-body"></div></div>';
html += ' <div class="popups-buttons"></div>'; //Maybe someday add the option for some specific buttons.
html += ' <div class="popups-footer"></div>'; //Maybe someday add some footer.
html += ' </div>';
html += ' </td>';
html += ' <td class="popups-cr popups-border"></td>';
html += ' </tr>';
html += ' <tr>';
html += ' <td class="popups-bl popups-border"></td>';
html += ' <td class="popups-b popups-border"></td>';
html += ' <td class="popups-br popups-border"></td>';
html += ' </tr>';
html += ' </table>';
html += ' </div>';
html += '</div>';
return html;
}
name = Custom content panes
description = Create custom, exportable, reusable content panes for applications like Panels.
core = 7.x
package = Chaos tool suite
dependencies[] = ctools
; Information added by drupal.org packaging script on 2013-04-03
version = "7.x-1.3"
core = "7.x"
project = "ctools"
datestamp = "1365013512"
<?php
/**
* Schema for CTools custom content.
*/
function ctools_custom_content_schema() {
return ctools_custom_content_schema_1();
}
function ctools_custom_content_schema_1() {
$schema = array();
$schema['ctools_custom_content'] = array(
'description' => 'Contains exportable customized content for this site.',
'export' => array(
'identifier' => 'content',
'bulk export' => TRUE,
'primary key' => 'cid',
'api' => array(
'owner' => 'ctools_custom_content',
'api' => 'ctools_content',
'minimum_version' => 1,
'current_version' => 1,
),
'create callback' => 'ctools_content_type_new',
),
'fields' => array(
'cid' => array(
'type' => 'serial',
'description' => 'A database primary key to ensure uniqueness',
'not null' => TRUE,
'no export' => TRUE,
),
'name' => array(
'type' => 'varchar',
'length' => '255',
'description' => 'Unique ID for this content. Used to identify it programmatically.',
),
'admin_title' => array(
'type' => 'varchar',
'length' => '255',
'description' => 'Administrative title for this content.',
),
'admin_description' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Administrative description for this content.',
'object default' => '',
),
'category' => array(
'type' => 'varchar',
'length' => '255',
'description' => 'Administrative category for this content.',
),
'settings' => array(
'type' => 'text',
'size' => 'big',
'description' => 'Serialized settings for the actual content to be used',
'serialize' => TRUE,
'object default' => array(),
),
),
'primary key' => array('cid'),
);
return $schema;
}
<?php
/**
* @file
* ctools_custom_content module
*
* This module allows styles to be created and managed on behalf of modules
* that implement styles.
*
* The ctools_custom_content tool allows recolorable styles to be created via a miniature
* scripting language. Panels utilizes this to allow administrators to add
* styles directly to any panel display.
*/
/**
* Implementation of hook_permission()
*/
function ctools_custom_content_permission() {
return array(
'administer custom content' => array(
'title' => t('Administer custom content'),
'description' => t('Add, edit and delete CTools custom stored custom content'),
),
);
}
/**
* Implementation of hook_ctools_plugin_directory() to let the system know
* we implement task and task_handler plugins.
*/
function ctools_custom_content_ctools_plugin_directory($module, $plugin) {
// Most of this module is implemented as an export ui plugin, and the
// rest is in ctools/includes/ctools_custom_content.inc
if ($module == 'ctools' && $plugin == 'export_ui') {
return 'plugins/' . $plugin;
}
}
/**
* Create callback for creating a new CTools custom content type.
*
* This ensures we get proper defaults from the plugin for its settings.
*/
function ctools_content_type_new($set_defaults) {
$item = ctools_export_new_object('ctools_custom_content', $set_defaults);
ctools_include('content');
$plugin = ctools_get_content_type('custom');
$item->settings = ctools_content_get_defaults($plugin, array());
return $item;
}
/**
* Implementation of hook_panels_dashboard_blocks().
*
* Adds page information to the Panels dashboard.
*/
function ctools_custom_content_panels_dashboard_blocks(&$vars) {
$vars['links']['ctools_custom_content'] = array(
'title' => l(t('Custom content'), 'admin/structure/ctools-content/add'),
'description' => t('Custom content panes are basic HTML you enter that can be reused in all of your panels.'),
);
// Load all mini panels and their displays.
ctools_include('export');
$items = ctools_export_crud_load_all('ctools_custom_content');
$count = 0;
$rows = array();
foreach ($items as $item) {
$rows[] = array(
check_plain($item->admin_title),
array(
'data' => l(t('Edit'), "admin/structure/ctools-content/list/$item->name/edit"),
'class' => 'links',
),
);
// Only show 10.
if (++$count >= 10) {
break;
}
}
if ($rows) {
$content = theme('table', array('rows' => $rows, 'attributes' => array('class' => 'panels-manage')));
}
else {
$content = '<p>' . t('There are no custom content panes.') . '</p>';
}
$vars['blocks']['ctools_custom_content'] = array(
'title' => t('Manage custom content'),
'link' => l(t('Go to list'), 'admin/structure/ctools-content'),
'content' => $content,
'class' => 'dashboard-content',
'section' => 'right',
);
}
<?php
$plugin = array(
'schema' => 'ctools_custom_content',
'access' => 'administer custom content',
'menu' => array(
'menu item' => 'ctools-content',
'menu title' => 'Custom content panes',
'menu description' => 'Add, edit or delete custom content panes.',
),
'title singular' => t('content pane'),
'title singular proper' => t('Content pane'),
'title plural' => t('content panes'),
'title plural proper' => t('Content panes'),
'handler' => 'ctools_custom_content_ui',
);
<?php
class ctools_custom_content_ui extends ctools_export_ui {
function edit_form(&$form, &$form_state) {
// Correct for an error that came in because filter format changed.
if (is_array($form_state['item']->settings['body'])) {
$form_state['item']->settings['format'] = $form_state['item']->settings['body']['format'];
$form_state['item']->settings['body'] = $form_state['item']->settings['body']['value'];
}
parent::edit_form($form, $form_state);
$form['category'] = array(
'#type' => 'textfield',
'#title' => t('Category'),
'#description' => t('What category this content should appear in. If left blank the category will be "Miscellaneous".'),
'#default_value' => $form_state['item']->category,
);
$form['title'] = array(
'#type' => 'textfield',
'#default_value' => $form_state['item']->settings['title'],
'#title' => t('Title'),
);
$form['body'] = array(
'#type' => 'text_format',
'#title' => t('Body'),
'#default_value' => $form_state['item']->settings['body'],
'#format' => $form_state['item']->settings['format'],
);
$form['substitute'] = array(
'#type' => 'checkbox',
'#title' => t('Use context keywords'),
'#description' => t('If checked, context keywords will be substituted in this content.'),
'#default_value' => !empty($form_state['item']->settings['substitute']),
);
}
function edit_form_submit(&$form, &$form_state) {
parent::edit_form_submit($form, $form_state);
// Since items in our settings are not in the schema, we have to do these manually:
$form_state['item']->settings['title'] = $form_state['values']['title'];
$form_state['item']->settings['body'] = $form_state['values']['body']['value'];
$form_state['item']->settings['format'] = $form_state['values']['body']['format'];
$form_state['item']->settings['substitute'] = $form_state['values']['substitute'];
}
function list_form(&$form, &$form_state) {
parent::list_form($form, $form_state);
$options = array('all' => t('- All -'));
foreach ($this->items as $item) {
$options[$item->category] = $item->category;
}
$form['top row']['category'] = array(
'#type' => 'select',
'#title' => t('Category'),
'#options' => $options,
'#default_value' => 'all',
'#weight' => -10,
);
}
function list_filter($form_state, $item) {
if ($form_state['values']['category'] != 'all' && $form_state['values']['category'] != $item->category) {
return TRUE;
}
return parent::list_filter($form_state, $item);
}
function list_sort_options() {
return array(
'disabled' => t('Enabled, title'),
'title' => t('Title'),
'name' => t('Name'),
'category' => t('Category'),
'storage' => t('Storage'),
);
}
function list_build_row($item, &$form_state, $operations) {
// Set up sorting
switch ($form_state['values']['order']) {
case 'disabled':
$this->sorts[$item->name] = empty($item->disabled) . $item->admin_title;
break;
case 'title':
$this->sorts[$item->name] = $item->admin_title;
break;
case 'name':
$this->sorts[$item->name] = $item->name;
break;
case 'category':
$this->sorts[$item->name] = $item->category;
break;
case 'storage':
$this->sorts[$item->name] = $item->type . $item->admin_title;
break;
}
$ops = theme('links__ctools_dropbutton', array('links' => $operations, 'attributes' => array('class' => array('links', 'inline'))));
$this->rows[$item->name] = array(
'data' => array(
array('data' => check_plain($item->name), 'class' => array('ctools-export-ui-name')),
array('data' => check_plain($item->admin_title), 'class' => array('ctools-export-ui-title')),
array('data' => check_plain($item->category), 'class' => array('ctools-export-ui-category')),
array('data' => $ops, 'class' => array('ctools-export-ui-operations')),
),
'title' => check_plain($item->admin_description),
'class' => array(!empty($item->disabled) ? 'ctools-export-ui-disabled' : 'ctools-export-ui-enabled'),
);
}
function list_table_header() {
return array(
array('data' => t('Name'), 'class' => array('ctools-export-ui-name')),
array('data' => t('Title'), 'class' => array('ctools-export-ui-title')),
array('data' => t('Category'), 'class' => array('ctools-export-ui-category')),
array('data' => t('Operations'), 'class' => array('ctools-export-ui-operations')),
);
}
}
The CTools Plugin Example is an example for developers of how to CTools
access, argument, content type, context, and relationship plugins.
There are a number of ways to profit from this:
1. The code itself intends to be as simple and self-explanatory as possible.
Nothing fancy is attempted: It's just trying to use the plugin API to show
how it can be used.
2. There is a sample panel. You can access it at /ctools_plugin_example/xxxx
to see how it works.
3. There is Advanced Help at admin/advanced_help/ctools_plugin_example.
\ No newline at end of file
name = Chaos Tools (CTools) Plugin Example
description = Shows how an external module can provide ctools plugins (for Panels, etc.).
package = Chaos tool suite
dependencies[] = ctools
dependencies[] = panels
dependencies[] = page_manager
dependencies[] = advanced_help
core = 7.x
; Information added by drupal.org packaging script on 2013-04-03
version = "7.x-1.3"
core = "7.x"
project = "ctools"
datestamp = "1365013512"
<?php
/*
* @file
*
* Working sample module to demonstrate CTools 3 plugins
*
* This sample module is only intended to demonstrate how external modules can
* provide ctools plugins. There is no useful functionality, and it's only
* intended for developers or for educational use.
*
* As far as possible, everything is kept very simple, not exercising all of
* the capabilities of CTools or Panels.
*
* Although the ctools documentation suggests that strict naming conventions
* be followed, this code attempts to follow only the conventions which are
* required (the hooks), in order to demonstrate the difference. You can
* certainly use the conventions, but it's important to know the difference
* between a convention and a requirement.
*
* The advanced_help module is required, because both CTools and this module
* provide help that way.
*
* There is a demonstration panel provided at /ctools_plugin_example/123
*/
/**
* Implements hook_menu
*/
function ctools_plugin_example_menu() {
$items = array();
$items["admin/settings/ctools_plugin_example"] = array(
'title' => 'CTools plugin example',
'description' => t("Demonstration code, advanced help, and a demo panel to show how to build ctools plugins."),
'page callback' => 'ctools_plugin_example_explanation_page',
'access arguments' => array('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Implements hook_ctools_plugin_directory().
*
* It simply tells panels where to find the .inc files that define various
* args, contexts, content_types. In this case the subdirectories of
* ctools_plugin_example/panels are used.
*/
function ctools_plugin_example_ctools_plugin_directory($module, $plugin) {
if ($module == 'ctools' && !empty($plugin)) {
return "plugins/$plugin";
}
}
/**
* Implement hook_ctools_plugin_api().
*
* If you do this, CTools will pick up default panels pages in
* <modulename>.pages_default.inc
*/
function ctools_plugin_example_ctools_plugin_api($module, $api) {
// @todo -- this example should explain how to put it in a different file.
if ($module == 'panels_mini' && $api == 'panels_default') {
return array('version' => 1);
}
if ($module == 'page_manager' && $api == 'pages_default') {
return array('version' => 1);
}
}
/**
* Just provide an explanation page for the admin section
* @return unknown_type
*/
function ctools_plugin_example_explanation_page() {
$content = '<p>' . t("The CTools Plugin Example is simply a developer's demo of how to create plugins for CTools. It provides no useful functionality for an ordinary user.") . '</p>';
$content .= '<p>' . t(
'There is a demo panel demonstrating much of the functionality provided at
<a href="@demo_url">CTools demo panel</a>, and you can find documentation on the examples at
!ctools_plugin_example_help.
CTools itself provides documentation at !ctools_help. Mostly, though, the code itself is intended to be the teacher.
You can find it in %path.',
array(
'@demo_url' => url('ctools_plugin_example/xxxxx'),
'!ctools_plugin_example_help' => theme('advanced_help_topic', array('module' => 'ctools_plugin_example', 'topic' => 'Chaos-Tools--CTools--Plugin-Examples', 'type' => 'title')),
'!ctools_help' => theme('advanced_help_topic', array('module' => 'ctools', 'topic' => 'plugins', 'type' => 'title')),
'%path' => drupal_get_path('module', 'ctools_plugin_example'),
)) . '</p>';
return $content;
}
<div id="node-16" class="node">
<div class="content clear-block">
<p>We can use access plugins to determine access to a page or visibility of the panes in a page. Basically, we just determine access based on configuration settings and the various contexts that are available to us.</p>
<p>The arbitrary example in plugins/access/arg_length.inc determines access based on the length of the simplecontext argument. You can configure whether access should be granted if the simplecontext argument is greater or less than some number.</p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
<div id="node-12" class="node">
<div class="content clear-block">
<p>Contexts are fundamental to CTools, and they almost always start with an argument to a panels page, so we'll start there too.</p>
<p>We first need to process an argument.</p>
<p>We're going to work with a "Simplecontext" context type and argument, and then with a content type that displays it. So we'll start by with the Simplecontext argument plugin in plugins/arguments/simplecontext_arg.inc.</p>
<p>Note that the name of the file (simplecontext_arg.inc) is built from the machine name of our plugin (simplecontext_arg). And note also that the primary function that we use to provide our argument (ctools_plugin_example_simplecontext_arg_ctools_arguments()) is also built from the machine name. This magic is most of the naming magic that you have to know.</p>
<p>You can browse plugins/arguments/simplecontext_arg.inc and see the little that it does.</p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
<div id="node-10" class="node">
<div class="content clear-block">
<p>This demonstration module is intended for developers to look at and play with. CTools plugins are not terribly difficult to do, but it can be hard to sort through the various arguments and required functions. The idea here is that you should have a starting point for most anything you want to do. Just work through the example, and then start experimenting with changing it.</p>
<p>There are two parts to this demo: </p>
<p>First, there is a sample panel provided that uses all the various plugins. It's at <a href="/ctools_plugin_example/12345">ctools_example/12345</a>. You can edit the panel and configure all the panes on it.</p>
<p>Second, the code is there for you to experiment with and change as you see fit. Sometimes starting with simple code and working with it can take you places that it's hard to go when you're looking at more complex examples.</p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
<div id="node-14" class="node">
<div class="content clear-block">
<p>Now we get to the heart of the matter: Building a content type plugin. A content type plugin uses the contexts available to it to display something. plugins/content_types/simplecontext_content_type.inc does this work for us.</p>
<p>Note that our content type also has an edit form which can be used to configure its behavior. This settings form is accessed through the panels interface, and it's up to you what the settings mean to the code and the generation of content in the display rendering.</p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
<div id="node-13" class="node">
<div class="content clear-block">
<p>Now that we have a plugin for a simplecontext argument, we can create a plugin for a simplecontext context. </p>
<p>Normally, a context would take an argument which is a key like a node ID (nid) and retrieve a more complex object from a database or whatever. In our example, we'll artificially transform the argument into an arbitrary "context" data object. </p>
<p>plugins/contexts/simplecontext.inc implements our context.</p>
<p>Note that there are actually two ways to create a context. The normal one, which we've been referring to, is to create a context from an argument. However, it is also possible to configure a context in a panel using the panels interface. This is quite inflexible, but might be useful for configuring single page. However, it means that we have a settings form for exactly that purpose. Our context would have to know how to create itself from a settings form as well as from an argument. Simplecontext can do that.</p>
<p>A context plugin can also provide keywords that expose parts of its context using keywords like masterkeyword:dataitem. The node plugin for ctools has node:nid and node:title, for example. The simplecontext plugin here provides the simplest of keywords.</p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
<div id="node-11" class="node">
<div class="content clear-block">
<p>Your module must provide a few things so that your plugins can be found.</p>
<p>First, you need to implement hook_ctools_plugin_directory(). Here we're telling CTools that our plugins will be found in the module's directory in the plugins/&lt;plugintype&gt; directory. Context plugins will be in ctools_plugin_example/plugins/contexts, Content-type plugins will be in ctools_plugin_example/plugins/content_types.</p>
<p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">ctools_plugin_example_ctools_plugin_directory</span><span style="color: #007700">(</span><span style="color: #0000BB">$module</span><span style="color: #007700">, </span><span style="color: #0000BB">$plugin</span><span style="color: #007700">) {<br />&nbsp; if (</span><span style="color: #0000BB">$module </span><span style="color: #007700">== </span><span style="color: #DD0000">'ctools' </span><span style="color: #007700">&amp;&amp; !empty(</span><span style="color: #0000BB">$plugin</span><span style="color: #007700">)) {<br />&nbsp;&nbsp;&nbsp; return </span><span style="color: #DD0000">"plugins/$plugin"</span><span style="color: #007700">;<br />&nbsp; }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p>
<p>Second, if you module wants to provide default panels pages, you can implement hook_ctools_plugin_api(). CTools will then pick up your panels pages in the file named &lt;modulename&gt;.pages_default.inc.</p>
<p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">ctools_plugin_example_ctools_plugin_api</span><span style="color: #007700">(</span><span style="color: #0000BB">$module</span><span style="color: #007700">, </span><span style="color: #0000BB">$api</span><span style="color: #007700">) {<br />&nbsp; if (</span><span style="color: #0000BB">$module </span><span style="color: #007700">== </span><span style="color: #DD0000">'panels_mini' </span><span style="color: #007700">&amp;&amp; </span><span style="color: #0000BB">$api </span><span style="color: #007700">== </span><span style="color: #DD0000">'panels_default'</span><span style="color: #007700">) {<br />&nbsp;&nbsp;&nbsp; return array(</span><span style="color: #DD0000">'version' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />&nbsp; }<br />&nbsp; if (</span><span style="color: #0000BB">$module </span><span style="color: #007700">== </span><span style="color: #DD0000">'page_manager' </span><span style="color: #007700">&amp;&amp; </span><span style="color: #0000BB">$api </span><span style="color: #007700">== </span><span style="color: #DD0000">'pages_default'</span><span style="color: #007700">) {<br />&nbsp;&nbsp;&nbsp; return array(</span><span style="color: #DD0000">'version' </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />&nbsp; }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
<div id="node-15" class="node">
<div class="content clear-block">
<p>Often a single data type can lead us to other data types. For example, a node has a user (the author) and the user has data associated with it.</p>
<p>A relationship plugin allows this kind of data to be accessed. </p>
<p>An example relationship plugin is provided in plugins/relationships/relcontext_from_simplecontext.inc. It looks at a simplecontext (which we got from an argument) and builds an (artificial) "relcontext" from that.</p>
</div>
<div class="clear-block">
<div class="meta">
</div>
</div>
</div>
[Chaos-Tools--CTools--Plugin-Examples]
title = CTools Plugin Examples
file = Chaos-Tools--CTools--Plugin-Examples
weight = 0
parent =
[Module-setup-and-hooks]
title = Module setup and hooks
file = Module-setup-and-hooks
weight = -15
parent = Chaos-Tools--CTools--Plugin-Examples
[Argument-Plugins--Starting-at-the-beginning]
title = Argument Plugins: Starting at the beginning
file = Argument-Plugins--Starting-at-the-beginning
weight = -14
parent = Chaos-Tools--CTools--Plugin-Examples
[Context-plugins--Creating-a--context--from-an-argument]
title = Context plugins: Creating a context from an argument
file = Context-plugins--Creating-a--context--from-an-argument
weight = -13
parent = Chaos-Tools--CTools--Plugin-Examples
[Content-Type-Plugins--Displaying-content-using-a-context]
title = Content Type Plugins: Displaying content using a context
file = Content-Type-Plugins--Displaying-content-using-a-context
weight = -12
parent = Chaos-Tools--CTools--Plugin-Examples
[Access-Plugins--Determining-access-and-visibility]
title = Access Plugins: Determining access and visibility
file = Access-Plugins--Determining-access-and-visibility
weight = -11
parent = Chaos-Tools--CTools--Plugin-Examples
[Relationships--Letting-one-context-take-us-to-another]
title = Relationships: Letting one context take us to another
file = Relationships--Letting-one-context-take-us-to-another
weight = -10
parent = Chaos-Tools--CTools--Plugin-Examples
<?php
/**
* @file
* Plugin to provide access control/visibility based on length of
* simplecontext argument (in URL).
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t("Arg length"),
'description' => t('Control access by length of simplecontext argument.'),
'callback' => 'ctools_plugin_example_arg_length_ctools_access_check',
'settings form' => 'ctools_plugin_example_arg_length_ctools_access_settings',
'summary' => 'ctools_plugin_example_arg_length_ctools_access_summary',
'required context' => new ctools_context_required(t('Simplecontext'), 'simplecontext'),
);
/**
* Settings form for the 'by role' access plugin.
*/
function ctools_plugin_example_arg_length_ctools_access_settings(&$form, &$form_state, $conf) {
$form['settings']['greater_than'] = array(
'#type' => 'radios',
'#title' => t('Grant access if simplecontext argument length is'),
'#options' => array(1 => t('Greater than'), 0 => t('Less than or equal to')),
'#default_value' => $conf['greater_than'],
);
$form['settings']['arg_length'] = array(
'#type' => 'textfield',
'#title' => t('Length of simplecontext argument'),
'#size' => 3,
'#default_value' => $conf['arg_length'],
'#description' => t('Access/visibility will be granted based on arg length.'),
);
}
/**
* Check for access.
*/
function ctools_plugin_example_arg_length_ctools_access_check($conf, $context) {
// As far as I know there should always be a context at this point, but this
// is safe.
if (empty($context) || empty($context->data)) {
return FALSE;
}
$compare = ($context->arg_length > $conf['arg_length']);
if (($compare && $conf['greater_than']) || (!$compare && !$conf['greater_than'])) {
return TRUE;
}
return FALSE;
}
/**
* Provide a summary description based upon the checked roles.
*/
function ctools_plugin_example_arg_length_ctools_access_summary($conf, $context) {
return t('Simpletext argument must be !comp @length characters',
array('!comp' => $conf['greater_than'] ? 'greater than' : 'less than or equal to',
'@length' => $conf['arg_length']));
}
<?php
/**
* @file
* Plugin to provide access control based upon role membership.
* This is directly from the ctools module, but serves as a good
* example of an access plugin
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t("CTools example: role"),
'description' => t('Control access by role.'),
'callback' => 'ctools_plugin_example_example_role_ctools_access_check',
'default' => array('rids' => array()),
'settings form' => 'ctools_plugin_example_example_role_ctools_access_settings',
'summary' => 'ctools_plugin_example_example_role_ctools_access_summary',
'required context' => new ctools_context_required(t('User'), 'user'),
);
/**
* Settings form for the 'by role' access plugin.
*/
function ctools_plugin_example_example_role_ctools_access_settings(&$form, &$form_state, $conf) {
$form['settings']['rids'] = array(
'#type' => 'checkboxes',
'#title' => t('Role'),
'#default_value' => $conf['rids'],
'#options' => ctools_get_roles(),
'#description' => t('Only the checked roles will be granted access.'),
);
}
/**
* Compress the roles allowed to the minimum.
*/
function ctools_plugin_example_example_role_ctools_access_settings_submit(&$form, &$form_state) {
$form_state['values']['settings']['rids'] = array_keys(array_filter($form_state['values']['settings']['rids']));
}
/**
* Check for access.
*/
function ctools_plugin_example_example_role_ctools_access_check($conf, $context) {
// As far as I know there should always be a context at this point, but this
// is safe.
if (empty($context) || empty($context->data) || !isset($context->data->roles)) {
return FALSE;
}
$roles = array_keys($context->data->roles);
$roles[] = $context->data->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
return (bool) array_intersect($conf['rids'], $roles);
}
/**
* Provide a summary description based upon the checked roles.
*/
function ctools_plugin_example_example_role_ctools_access_summary($conf, $context) {
if (!isset($conf['rids'])) {
$conf['rids'] = array();
}
$roles = ctools_get_roles();
$names = array();
foreach (array_filter($conf['rids']) as $rid) {
$names[] = check_plain($roles[$rid]);
}
if (empty($names)) {
return t('@identifier can have any role', array('@identifier' => $context->identifier));
}
return format_plural(count($names), '@identifier must have role "@roles"', '@identifier can be one of "@roles"', array('@roles' => implode(', ', $names), '@identifier' => $context->identifier));
}
<?php
/**
* @file
*
* Sample plugin to provide an argument handler for a simplecontext.
*
* Given any argument to the page, simplecontext will get it
* and turn it into a piece of data (a "context") just by adding some text to it.
* Normally, the argument would be a key into some database (like the node
* database, for example, and the result of using the argument would be to load
* a specific "context" or data item that we can use elsewhere.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t("Simplecontext arg"),
// keyword to use for %substitution
'keyword' => 'simplecontext',
'description' => t('Creates a "simplecontext" from the arg.'),
'context' => 'simplecontext_arg_context',
// 'settings form' => 'simplecontext_arg_settings_form',
// placeholder_form is used in panels preview, for example, so we can
// preview without getting the arg from a URL
'placeholder form' => array(
'#type' => 'textfield',
'#description' => t('Enter the simplecontext arg'),
),
);
/**
* Get the simplecontext context using the arg. In this case we're just going
* to manufacture the context from the data in the arg, but normally it would
* be an API call, db lookup, etc.
*/
function simplecontext_arg_context($arg = NULL, $conf = NULL, $empty = FALSE) {
// If $empty == TRUE it wants a generic, unfilled context.
if ($empty) {
return ctools_context_create_empty('simplecontext');
}
// Do whatever error checking is required, returning FALSE if it fails the test
// Normally you'd check
// for a missing object, one you couldn't create, etc.
if (empty($arg)) {
return FALSE;
}
return ctools_context_create('simplecontext', $arg);
}
This diff is collapsed.
This diff is collapsed.
<p>Access plugins allow context based access control to pages.</p>
<pre> 'title' => Title of the plugin
'description' => Description of the plugin
'callback' => callback to see if there is access is available. params: $conf, $contexts, $account
'required context' => zero or more required contexts for this access plugin
'default' => an array of defaults or a callback giving defaults
'settings form' => settings form. params: &$form, &$form_state, $conf
settings form validate
settings form submit
</pre>
<p><strong>Warning:</strong> your settings array will be stored <strong>in the meny system</strong> to reduce loads, so be <strong>trim</strong>.</p>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment