Câu trả lời:
Thỉnh thoảng khi làm việc với trình quản lý Trang và Bảng điều khiển , rất hữu ích khi thêm các bổ trợ Ctools tùy chỉnh.
Ctools plugin đi kèm trong một số lượng lớn các hình thức, và các module khác, chẳng hạn như Feeds , Addressfield và Openlayers tất cả tận dụng Ctools để cung cấp các plugin mở rộng bởi các module khác. Các dạng phổ biến nhất của plugin, có lẽ là "loại nội dung" và "quyền truy cập". Đầu tiên không được nhầm lẫn với "nội dung" thực thể và các gói của nó, còn được gọi là các loại nội dung.
Đầu tiên, bản tóm tắt :
Đối với bất kỳ mô-đun nào để cung cấp các plugin ctools, trước tiên họ nên cho Ctools biết nơi cần tìm chúng. Móc bên dưới, nói rằng chúng tôi cung cấp bổ trợ cho ctools, thuộc loại "content_types" và "access". Chức năng có thể được làm đơn giản hơn, nhưng bằng cách này, chúng tôi đảm bảo rằng chỉ có mô-đun đúng được thông báo về các plugin, cũng như chỉ quét đĩa để tìm tệp khi chúng tôi thực sự cung cấp loại plugin được yêu cầu.
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;
}
}
Dưới đây là một cấu trúc thư mục ví dụ cho một mô-đun cung cấp hai plugin. Một loại nội dung và một plugin truy cập.
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
Plugin loại nội dung
Một loại nội dung trong từ vựng Ctools, thường được gọi là "Ngăn", như được cung cấp bởi Chế độ xem ví dụ. Trong câu hỏi này: Có cách nào để chặn danh sách NID được tạo bởi một chế độ xem và sử dụng chúng làm bộ lọc cho chế độ xem khác không? , tác giả hỏi về lập luận cho ăn lập trình để xem. Mặc dù bản thân nó không khó lắm, nhưng câu hỏi tiếp theo nhanh chóng trở thành: "Làm thế nào để tôi hiển thị kết quả?".
Một câu trả lời, sẽ là tạo ra một "loại nội dung" mới.
Bây giờ, plugin loại nội dung thực tế, một lần nữa sử dụng câu hỏi Lượt xem từ phía trên, có thể trông như thế này:
$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;
}
Khi mô-đun này được bật, giờ đây sẽ có một danh mục mới trong Bảng điều khiển, 'Danh mục tùy chỉnh của tôi', trong đó người ta sẽ tìm thấy một khung duy nhất, hiển thị mã từ phía trên.
Truy cập plugin
Plugin truy cập bên dưới sẽ cung cấp khả năng ghi lại các biến thể và / hoặc bảng dựa trên độ sâu của thuật ngữ được đo từ gốc của từ vựng.
<?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];
}
Các plugin CTools là các tệp nhỏ có thể là một phần của bất kỳ mô-đun nào như là cách để mở rộng chức năng của nó. Chúng có thể được sử dụng để cung cấp các thành phần (panes), thêm các tùy chọn kiểu bổ sung vào bảng của bạn, v.v.
Vui lòng kiểm tra các plugin CTools không có bảng điều khiển để biết tài liệu từng bước. Vì vậy, ngắn gọn nó đi như sau:
Bạn cần thêm các phụ thuộc CTools vào .info
tệp của mình dưới dạng:
dependencies[] = ctools
dependencies[] = panels
Nói với CTools nơi plugin của bạn được đặt:
<?php
function MYMODULE_ctools_plugin_directory($module, $plugin) {
if (($module == 'ctools') && ($plugin == 'content_types')) {
return 'plugins/content_types';
}
}
?>
Thực hiện plugin trong một .inc
tệp (theo mặc định là $module.$api.inc
). Mã plugin ví dụ:
<?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;
}
?>
Vị trí mặc định của các plugin trông giống như:
MYMODULE/
plugins/
content_types/
templates/
MYMODULE.info
MYMODULE.module
Để biết thêm ví dụ, vui lòng kiểm tra ctools_plugin_example
mô-đun là một phần của mô-đun CTools hoặc kiểm tra trang Trợ giúp ( Ví dụ về Trình cắm CTools ) trong Giao diện người dùng Drupal sau khi bật mô-đun.
Trong Drupal 8, đây là một phần của lõi (xem: Drupal \ Element \ Plugin ) và nó cung cấp tính kế thừa đối tượng, giao diện đối tượng và đóng gói tệp đơn. Xem: Drupal 8 ngay bây giờ: Các plugin hướng đối tượng trong Drupal 7