回答:
すべての今して作業する場合Ctoolsページマネージャ、およびパネル、カスタムCtoolsプラグインを追加すると便利です。
Ctoolsプラグインには多数の形式があり、Feeds、Addressfield、Openlayersなどの他のモジュールはすべてCtoolsを使用して、他のモジュールで拡張可能なプラグインを提供します。プラグインの最も一般的な形式は、おそらく「コンテンツタイプ」と「アクセス」です。最初のエンティティは、エンティティ「コンテンツ」およびコンテンツタイプとも呼ばれるそのバンドルと混同しないでください。
まず、ボイラープレート:
ctoolsプラグインを提供するモジュールについては、最初にCtoolsにそれらを探す場所を指示する必要があります。以下のフックは、「content_types」および「access」タイプのctoolsのプラグインを提供することを示しています。関数をより簡単にすることもできますが、この方法では、適切なモジュールのみがプラグインについて通知されるようにし、要求されているタイプのプラグインを実際に提供するときにのみファイルのディスクをスキャンします。
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;
}
}
以下は、2つのプラグインを提供するモジュールのディレクトリ構造の例です。1つのコンテンツタイプと1つのアクセスプラグイン。
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
コンテンツタイププラグイン
Ctoolsボキャブラリのコンテンツタイプは、ビューなどで提供される「ペイン」として知られています。この質問では、ビューによって作成されたNIDのリストをインターセプトし、それらを別のビューのフィルターとして使用する方法はありますか?、著者はビューにプログラムで引数を与えることについて尋ねます。それ自体はそれほど難しくはありませんが、フォローアップの質問はすぐに「結果を表示するにはどうすればよいですか?」になります。
1つの答えは、新しい「コンテンツタイプ」を作成することです。
さて、実際のコンテンツタイププラグインは、上記のビューの質問を再び使用して、次のようになります。
$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;
}
このモジュールを有効にすると、Panelsに新しいカテゴリ「My custom category」が追加され、1つのペインが表示され、上からコードがレンダリングされます。
アクセスプラグイン
以下のアクセスプラグインは、語彙のルートから測定された用語の深さに基づいて、バリアントやペインをファイリングする機能を提供します。
<?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プラグインは、機能を拡張する方法として任意のモジュールの一部にできる小さなファイルです。コンポーネント(ペイン)の提供、パネルへのスタイルオプションの追加などに使用できます。
ステップごとのドキュメントについては、PanelsページのないCToolsプラグインを確認してください。簡単に言うと、次のようになります。
次のように、CToolsの依存関係を.info
ファイルに追加する必要があります。
dependencies[] = ctools
dependencies[] = panels
プラグインの場所をCToolsに伝えます。
<?php
function MYMODULE_ctools_plugin_directory($module, $plugin) {
if (($module == 'ctools') && ($plugin == 'content_types')) {
return 'plugins/content_types';
}
}
?>
.inc
ファイルにプラグインを実装します(デフォルトでは$module.$api.inc
)。プラグインコードの例:
<?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;
}
?>
プラグインのデフォルトの場所は次のようになります。
MYMODULE/
plugins/
content_types/
templates/
MYMODULE.info
MYMODULE.module
その他の例についてctools_plugin_example
は、CToolsモジュールの一部としてモジュールを確認するか、モジュールを有効にした後、Drupal UI のヘルプページ(CToolsプラグインの例)をチェックアウトしてください。
Drupal 8では、これはコアの一部になり(Drupal \ Component \ Pluginを参照)、オブジェクトの継承、オブジェクトインターフェイス、および単一ファイルのカプセル化を提供します。参照:Drupal 8 Now:Drupal 7のオブジェクト指向プラグイン