Was sind Ctools-Plugins und wie erstellt man sie?
quelle
Bei der Arbeit mit Ctools Page Manager und Panels ist es von Zeit zu Zeit hilfreich, benutzerdefinierte Ctools-Plugins hinzuzufügen.
Ctools-Plugins gibt es in einer Vielzahl von Formen, und andere Module wie Feeds , Adressfelder und OpenLayer verwenden Ctools, um Plugins bereitzustellen, die durch andere Module erweiterbar sind. Die gebräuchlichsten Formen von Plugins sind jedoch wahrscheinlich "Inhaltstyp" und "Zugriff". Die erste darf nicht mit der Entität "Inhalt" und ihren Bündeln, auch Inhaltstypen genannt, verwechselt werden.
Zunächst das Boilerplate :
Damit ein Modul ctools-Plug-ins bereitstellt, muss es Ctools zunächst mitteilen, wo es nach ihnen suchen soll. Der folgende Haken besagt, dass wir Plugins für ctools vom Typ "content_types" und "access" bereitstellen. Die Funktion könnte einfacher gemacht werden, aber auf diese Weise stellen wir sicher, dass nur das richtige Modul über die Plugins informiert wird und dass es die Festplatte nur nach Dateien durchsucht, wenn wir tatsächlich den Typ des gewünschten Plugins bereitstellen.
function HOOK_ctools_plugin_directory($owner, $plugin_type) {
// We'll be nice and limit scandir() calls.
if ($owner == 'ctools' && ($plugin_type == 'content_types' || $plugin_type == 'access')) {
return 'plugins/' . $plugin_type;
}
}
Im Folgenden finden Sie eine Beispielverzeichnisstruktur für ein Modul, das zwei Plugins bereitstellt. Ein Inhaltstyp und ein Zugriffs-Plugin.
module/
module/module.info
module/module.module
module/plugins/
module/plugins/content_types/
module/plugins/content_types/two_views_in_one.inc
module/plugins/access/
module/plugins/access/term_depth.inc
Inhaltstyp-Plugin
Ein Inhaltstyp im Ctools-Vokabular wird häufiger als "Bereich" bezeichnet, wie dies beispielsweise in Ansichten angegeben ist. In dieser Frage: Gibt es eine Möglichkeit, eine Liste von NIDs, die von einer Ansicht erstellt wurden, abzufangen und als Filter für eine andere Ansicht zu verwenden? fragt der Autor nach der programmgesteuerten Eingabe von Argumenten in eine Ansicht. Während das an sich nicht sehr schwer ist, wird die Folgefrage schnell zu "Wie zeige ich die Ergebnisse an?".
Eine Antwort wird darin bestehen, einen neuen "Inhaltstyp" zu erstellen.
Nun könnte das Plugin für den eigentlichen Inhaltstyp unter Verwendung der obigen Frage "Ansichten" folgendermaßen aussehen:
$plugin = array(
'title' => t('Render a View with arguments from another'),
'single' => TRUE,
'category' => array(t('My custom category'), -9),
// Despite having no "settings" we need this function to pass back a form, or we'll loose the context and title settings.
'edit form' => 'module_content_type_edit_form',
'render callback' => 'module_content_type_render',
);
function module_content_type_render($subtype, $conf, $args, $context = NULL) {
$block = new stdClass;
$block->title = 'My View';
$view = views_get_view('get_nids');
$view->preview('display_machine_name', array($arg1, $arg2));
$nids = '';
foreach($view->result as $node) {
$nids += $node->nid . ',';
}
$nids = rtrim($nids, ',');
$view = views_get_view('get_related');
$view->execute_display('display_machine_name', array($nids));
$block->content = $view->render();
return $block;
}
/**
* 'Edit form' callback for the content type.
*/
function module_content_type_edit_form($form, &$form_state) {
// No settings beyond context, which has already been handled.
return $form;
}
Wenn dieses Modul aktiviert ist, sollte es jetzt eine neue Kategorie in den Bereichen "Meine benutzerdefinierte Kategorie" geben, in der sich ein einzelner Bereich befinden sollte, in dem der Code von oben dargestellt wird.
Zugriffs-Plugin
Das folgende Access-Plugin bietet die Möglichkeit, Varianten und / oder Fenster basierend auf der Tiefe eines Begriffs, gemessen an der Wurzel des Vokabulars, auszufiltern.
<?php
/**
* @file
* Plugin to provide access control based upon a parent term.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t("Taxonomy: term depth"),
'description' => t('Control access by the depth of a term.'),
'callback' => 'term_depth_term_depth_ctools_access_check',
'default' => array('vid' => array(), 'depth' => 0),
'settings form' => 'term_depth_term_depth_ctools_access_settings',
'settings form validation' => 'term_depth_term_depth_ctools_access_settings_validate',
'settings form submit' => 'term_depth_term_depth_ctools_access_settings_submit',
'summary' => 'term_depth_term_depth_ctools_access_summary',
'required context' => new ctools_context_required(t('Term'), array('taxonomy_term', 'terms')),
);
/**
* Settings form for the 'term depth' access plugin.
*/
function term_depth_term_depth_ctools_access_settings($form, &$form_state, $conf) {
// If no configuration was saved before, set some defaults.
if (empty($conf)) {
$conf = array(
'vid' => 0,
);
}
if (!isset($conf['vid'])) {
$conf['vid'] = 0;
}
// Loop over each of the configured vocabularies.
foreach (taxonomy_get_vocabularies() as $vid => $vocabulary) {
$options[$vid] = $vocabulary->name;
}
$form['settings']['vid'] = array(
'#title' => t('Vocabulary'),
'#type' => 'select',
'#options' => $options,
'#description' => t('Select the vocabulary for this form. If there exists a parent term in that vocabulary, this access check will succeed.'),
'#id' => 'ctools-select-vid',
'#default_value' => $conf['vid'],
'#required' => TRUE,
);
$form['settings']['depth'] = array(
'#title' => t('Depth'),
'#type' => 'textfield',
'#description' => t('Set the required depth of the term. If the term exists at the right depth, this access check will succeed.'),
'#default_value' => $conf['depth'],
'#required' => TRUE,
);
return $form;
}
/**
* Submit function for the access plugins settings.
*
* We cast all settings to numbers to ensure they can be safely handled.
*/
function term_depth_term_depth_ctools_access_settings_submit($form, $form_state) {
foreach (array('depth', 'vid') as $key) {
$form_state['conf'][$key] = (integer) $form_state['values']['settings'][$key];
}
}
/**
* Check for access.
*/
function term_depth_term_depth_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) || empty($context->data->vid) || empty($context->data->tid)) {
return FALSE;
}
// Get the $vid.
if (!isset($conf['vid'])) {
return FALSE;
}
$depth = _term_depth($context->data->tid);
return ($depth == $conf['depth']);
}
/**
* Provide a summary description based upon the checked terms.
*/
function term_depth_term_depth_ctools_access_summary($conf, $context) {
$vocab = taxonomy_vocabulary_load($conf['vid']);
return t('"@term" has parent in vocabulary "@vocab" at @depth', array(
'@term' => $context->identifier,
'@vocab' => $vocab->name,
'@depth' => $conf['depth'],
));
}
/**
* Find the depth of a term.
*/
function _term_depth($tid) {
static $depths = array();
if (!isset($depths[$tid])) {
$parent = db_select('taxonomy_term_hierarchy', 'th')
->fields('th', array('parent'))
->condition('tid', $tid)
->execute()->fetchField();
if ($parent == 0) {
$depths[$tid] = 1;
}
else {
$depths[$tid] = 1 + _term_depth($parent);
}
}
return $depths[$tid];
}
CTools-Plugins sind kleine Dateien, die Teil jedes Moduls sein können, um dessen Funktionalität zu erweitern. Sie können verwendet werden, um Komponenten (Fenster) bereitzustellen, Ihren Fenstern zusätzliche Stiloptionen hinzuzufügen usw.
Bitte überprüfen Sie die CTools Plugins ohne Panels Seite für eine schrittweise Dokumentation. So kurz geht es:
Sie müssen CTools-Abhängigkeiten in Ihre
.info
Datei einfügen als:Teilen Sie CTools mit, wo sich Ihr Plugin befindet:
Plugin in eine
.inc
Datei implementieren (standardmäßig als$module.$api.inc
). Beispiel für einen Plugin-Code:Der Standardspeicherort der Plugins sieht folgendermaßen aus:
Weitere Beispiele finden Sie im
ctools_plugin_example
Modul CTools oder auf der Hilfeseite ( CTools-Plugin-Beispiele ) in der Drupal-Benutzeroberfläche, nachdem Sie das Modul aktiviert haben.In Drupal 8 ist dies nun Teil des Kerns (siehe: Drupal \ Component \ Plugin ) und bietet Objektvererbung, Objektschnittstellen und Einzeldateikapselung. Siehe: Drupal 8 Jetzt: Objektorientierte Plugins in Drupal 7
quelle