Odpowiedzi:
Od czasu do czasu podczas pracy z menedżerem stron Ctools i panelami przydatne jest dodawanie niestandardowych wtyczek Ctools.
Wtyczki Ctools występują w wielu formach, a inne moduły, takie jak Kanały , Pole Adresowe i Openlayers, wykorzystują Ctools do zapewnienia wtyczek rozszerzalnych o inne moduły. Najpopularniejsze formy wtyczek to prawdopodobnie „typ zawartości” i „dostęp”. Pierwszego nie należy mylić z bytem „treść” i jego pakietami, zwanymi także typami treści.
Najpierw płyta kotła :
Aby każdy moduł udostępniał wtyczki Ctools, powinien najpierw powiedzieć Ctools, gdzie ich szukać. Poniższy haczyk mówi, że zapewniamy wtyczki do narzędzi ctools typu „content_types” i „access”. Funkcję tę można uprościć, ale w ten sposób upewniamy się, że tylko odpowiedni moduł jest informowany o wtyczkach, a także skanujemy dysk w poszukiwaniu plików, gdy faktycznie zapewniamy żądany typ wtyczki.
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;
}
}
Poniżej znajduje się przykładowa struktura katalogów modułu udostępniającego dwie wtyczki. Jeden typ zawartości i jedna wtyczka dostępu.
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
Wtyczka typu zawartości
Typ zawartości w słownictwie Ctools jest częściej znany jako „okienko”, na przykład w widokach. W tym pytaniu: Czy istnieje sposób na przechwycenie listy identyfikatorów NID utworzonych przez widok i użycie ich jako filtra dla innego widoku? , autor pyta o programowe podawanie argumentów do widoku. Chociaż nie jest to zbyt trudne, pytanie uzupełniające szybko brzmi: „Jak wyświetlić wyniki?”.
Jedną odpowiedzią będzie utworzenie nowego „typu zawartości”.
Teraz rzeczywista wtyczka typu zawartości, ponownie przy użyciu pytania Widoki z góry, może wyglądać tak:
$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;
}
Po włączeniu tego modułu w panelach powinna być teraz nowa kategoria „Moja niestandardowa kategoria”, w której należy znaleźć pojedynczy panel, renderujący kod z góry.
Wtyczka dostępu
Wtyczka dostępu poniżej zapewni możliwość wyodrębnienia wariantów i / lub paneli na podstawie głębokości terminu, mierzonej od źródła słownictwa.
<?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];
}
Wtyczki CTools to małe pliki, które mogą być częścią dowolnego modułu jako sposób na rozszerzenie jego funkcjonalności. Można ich używać do dostarczania komponentów (paneli), dodawania dodatkowych opcji stylów do paneli itp.
Sprawdź krok po kroku stronę Wtyczki CTools bez paneli . Tak krótko wygląda to tak:
Musisz dodać zależności CTools do swojego .info
pliku jako:
dependencies[] = ctools
dependencies[] = panels
Powiedz CTools, gdzie znajduje się Twoja wtyczka:
<?php
function MYMODULE_ctools_plugin_directory($module, $plugin) {
if (($module == 'ctools') && ($plugin == 'content_types')) {
return 'plugins/content_types';
}
}
?>
Zaimplementuj wtyczkę w .inc
pliku (domyślnie jako $module.$api.inc
). Przykładowy kod wtyczki:
<?php
$plugin = array(
'title' => t('Twitter feed'),
'description' => t('Twitter feed'),
'category' => 'Widgets',
'icon' => '',
'render callback' => 'twitter_block',
'defaults' => array(),
);
// render callback
function twitter_block() {
// Add twitter widget javascript
$url = TWITTER_USER
$widget_id = TWITTER_WIDGET_ID;
$data = array();
$data['url'] = $url;
$data['widget_id'] = $widget_id;
$content = array(
'#theme' => 'my_block',
'#content' => $data,
);
$block = new stdClass();
$block->content = $content;
$block->title = '';
$block->id = 'twitter_block';
return $block;
}
?>
Domyślna lokalizacja wtyczek wygląda następująco:
MYMODULE/
plugins/
content_types/
templates/
MYMODULE.info
MYMODULE.module
Aby uzyskać więcej przykładów, sprawdź ctools_plugin_example
moduł, który jest częścią modułu CTools, lub sprawdź stronę pomocy ( Przykłady wtyczek CTools ) w interfejsie Drupal po włączeniu modułu.
W Drupal 8 jest to teraz część rdzenia (patrz: Drupal \ Component \ Plugin ) i zapewnia dziedziczenie obiektów, interfejsy obiektów i enkapsulację pojedynczych plików. Zobacz: Drupal 8 Teraz: Wtyczki obiektowe w Drupal 7