Skip to content

Instantly share code, notes, and snippets.

@steinmb
Last active December 21, 2015 19:29
Show Gist options
  • Save steinmb/6354634 to your computer and use it in GitHub Desktop.
Save steinmb/6354634 to your computer and use it in GitHub Desktop.
Stolen from @seanr with his blessing. Releasing the power of EntityFieldQuery(). The basic idea with this code is it's a ctools content type that allows you to dynamically build a sort of "mini-view" with a very limited set of options, so the user can arbitrarily pull content according to a limited set of criteria and then display it in the chos…
<?php
/**
* @file
*
* Note that there is no need for a hook_block() to define it. CTools automatically scans all
* of the subdirectories here for *.inc files, and reads the contents of the $plugin array
* defined below to figure out how to use the widget.
*/
$plugin = array(
// Note: The widget's "name' is inherited from the name of the *.inc file. So this widget
// is "test_pane".
// These settings control where the widget appears in the Panels "Add New Content" menu.
'title' => t('Full width Editorial Pod'),
'description' => t('A full width editorial pod allowing you to specify a content type, quantity, and view mode.'),
'category' => array(t('WWE Widgets'), -9),
// Do a search/replace in this file for "test_pane" and change it to whatever you want to
// name your widget.
'content_types' => array('wwe_widgets_full_width'),
// Customize each of the functions listed below per the instructions provided with each function.
'render callback' => 'wwe_widgets_full_width_render',
// If you don't need any settings of your own you can use 'wwe_widgets_form_defaults'
// instead and omit the wwe_ep_custom_edit_form() function.
'edit form' => 'wwe_widgets_full_width_edit_form',
// The information displayed on the admin screen may be customized for widgets that would
// benefit from that - maybe to show a thumb of an image used for image-driven widgets?
'admin info' => 'wwe_widgets_full_width_admin_info',
// If you provide settings in your config form, you need to provide defaults for each setting.
'defaults' => array(
'content_type' => array('article' => 'article'),
'pillar' => '',
'tags' => '',
'quantity' => 3,
'view_mode' => 'teaser',
),
// Don't touch this
'single' => TRUE,
);
/**
* Content block. Output the front-end HTML code for the widget.
*/
function wwe_widgets_full_width_render($subtype, $conf, $args, $context) {
$block = new stdClass();
// Collect a list of nids based on the widget's saved settings
// TODO: get pillar from context?
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', $conf['content_type'])
->propertyCondition('status', 1)
->propertyOrderBy('sticky', 'DESC')
->propertyOrderBy('created', 'DESC')
->range(0, $conf['quantity'])
->addMetaData('account', user_load(1)); // Run the query as user 1.
// These parameters may have null values.
if (!empty($conf['pillar'])) $query->fieldCondition('field_pillars', 'tid', $conf['pillar']);
if (!empty($conf['tags'])) $query->fieldCondition('field_tags', 'tid', $conf['tags']);
$result = $query->execute();
$nodes = array();
if (isset($result['node'])) {
// All we want is the nids, then we'll render them the normal way with the specified view mode
$nids = array_keys($result['node']);
foreach ($nids as $nid) {
$node = node_load($nid);
$content = node_view($node, $conf['view_mode']);
$nodes[] = drupal_render($content);
}
}
$block->title = 'Custom editorial pod';
// You may specify panel utility classes (row and column grid sizes and application of corners)
// or any other utility classes you might need to apply in css_class.
$block->css_class = 'wwe-widgets-full-width count-' . $conf['quantity'];
$block->content = implode(PHP_EOL, $nodes);
return $block;
}
/**
* Admin interface content block.
*/
function wwe_widgets_full_width_admin_info($subtype, $conf, $contexts) {
$block = new stdClass();
$html = array();
// Show some summary information that might be helpful to the user. This should usually be a
// brief listing of the config settings.
$html[] = '<pre>';
if (!empty($conf['content_type'])) $html[] = 'Content type: ' . implode(', ', array_keys($conf['content_type']));
if (!empty($conf['pillar'])) $html[] = 'Pillar: ' . implode(', ', array_keys($conf['pillar']));
if (!empty($conf['tags'])) $html[] = 'Tags: ' . implode(', ', array_keys($conf['tags']));
$html[] = 'Quantity: ' . $conf['quantity'];
$html[] = 'View mode: ' . $conf['view_mode'];
$html[] = '</pre>';
// We don't show a title - it would be redundant. There will already be a title on the pane
// itself as set in the $plugin() array at the top of this file.
$block->title = '';
$block->content = implode(PHP_EOL, $html);
return $block;
}
/**
* Settings form.
*/
function wwe_widgets_full_width_edit_form($form, &$form_state) {
$form = wwe_widgets_form_defaults($form, $form_state);
$conf = $form_state['conf'];
// TODO: Here is theoretically where we can pull in info from panel context
//$form = wwe_ep_form_defaults($form, $form_state);
// Grab our available options
$fields = field_info_fields();
$types = node_type_get_names();
$pillars = taxonomy_allowed_values($fields['field_pillars']);
$tags = taxonomy_allowed_values($fields['field_tags']);
$modes = array();
$entity_info = entity_get_info('node');
foreach ($entity_info['view modes'] as $mode => $mode_info) {
if (strpos($mode, 'ep_') !== FALSE) {
$modes[$mode] = $mode_info['label'];
}
}
// Widget configuration screens use Drupal's standard Form API. This is a sample text field.
// Note how the default value is specified - this provides for a default for new widgets and
// for editing previously-configured widgets.
$form['content_type'] = array(
'#type' => 'select',
'#title' => t('Content type'),
'#description' => t('Choose the content type you wish to display.'),
'#options' => $types,
'#default_value' => $conf['content_type'],
'#required' => TRUE,
'#multiple' => TRUE,
);
$form['pillar'] = array(
'#type' => 'select',
'#title' => t('Pillar'),
'#description' => t('Choose the pillar from which to select content.'),
'#options' => $pillars,
'#default_value' => $conf['pillar'],
'#empty_option' => '- Select -',
'#multiple' => TRUE,
);
$form['tags'] = array(
'#type' => 'select',
'#title' => t('Tags'),
'#description' => t('Choose the tags from which to select content.'),
'#options' => $tags,
'#default_value' => $conf['tags'],
'#empty_option' => '- Select -',
'#multiple' => TRUE,
'#size' => 15,
);
$form['quantity'] = array(
'#type' => 'select',
'#title' => t('Display type'),
'#options' => array(
3 => 'Three slot gallery',
4 => 'Four slot gallery',
),
'#description' => t('Enter the number of nodes to display.'),
'#default_value' => $conf['quantity'],
'#required' => TRUE,
);
$form['view_mode'] = array(
'#type' => 'select',
'#title' => t('View mode'),
'#description' => t('Choose the view mode in which to display selected content.'),
'#options' => $modes,
'#default_value' => $conf['view_mode'],
'#required' => TRUE,
);
//$form['#submit'][] = 'wwe_ep_widget_form_submit';
return $form;
}
@seanr
Copy link

seanr commented Aug 27, 2013

The basic idea with this code is it's a ctools content type that allows you to dynamically build a sort of "mini-view" with a very limited set of options, so the user can arbitrarily pull content according to a limited set of criteria and then display it in the chosen view mode. Pillar refers to one of four top level sections of the site (just a vocabulary with four terms). This will display either three or four items (display type). The render function uses EFQ to build the base query and adds the conditions based on the settings. This could pretty easily be extracted out into a module if you wanted to spend the time on it, so you could almost treat it like a node type with a bunch of options that then dynamically builds the query which would essentially get you a lightweight views replacement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment