noderelationships.module in Node Relationships 6
This is the main script for the noderelationships module. It merely contains the implementation of hooks invoked by Drupal core, CCK, Views, etc. All common functions are externalized into several scripts that are included on demand.
File
noderelationships.moduleView source
<?php
/**
* @file
* This is the main script for the noderelationships module. It merely contains
* the implementation of hooks invoked by Drupal core, CCK, Views, etc.
* All common functions are externalized into several scripts that are included
* on demand.
*/
/**
* Back reference regions.
*/
define('NODERELATIONSHIPS_BACKREF_REGION_FIELD', 'field');
define('NODERELATIONSHIPS_BACKREF_REGION_PAGE', 'page');
define('NODERELATIONSHIPS_BACKREF_REGION_TAB', 'tab');
/**
* Views related constants.
*/
define('NODERELATIONSHIPS_BACKREF_VIEW_NAME', 'noderelationships_backref');
define('NODERELATIONSHIPS_BACKREF_VIEW_TAG', 'noderelationships_backref');
define('NODERELATIONSHIPS_NODEREF_VIEW_NAME', 'noderelationships_noderef');
define('NODERELATIONSHIPS_NODEREF_VIEW_TAG', 'noderelationships_noderef');
define('NODERELATIONSHIPS_VIEW_PATH_PREFIX', 'noderelationships');
/**
* Implementation of hook_theme().
*/
function noderelationships_theme() {
module_load_include('inc', 'noderelationships', 'noderelationships.system');
return _noderelationships_theme();
}
/**
* Implementation of hook_menu().
*/
function noderelationships_menu() {
module_load_include('inc', 'noderelationships', 'noderelationships.system');
return _noderelationships_menu();
}
/**
* Access callback for the node relationships tab.
*
* @see noderelationships_menu()
*/
function noderelationships_backref_access($referred_node) {
// Deny access if the user does not have access to view the referred node.
if (!node_access('view', $referred_node)) {
return FALSE;
}
// Include common module functions.
module_load_include('inc', 'noderelationships');
// Obtain back reference settings for this type.
$backref_settings = noderelationships_settings_load($referred_node->type, 'backref');
// Deny access (meaning the tab is not visible) when the node type
// does not have back references enabled for this region.
if (empty($backref_settings['regions'][NODERELATIONSHIPS_BACKREF_REGION_TAB])) {
return FALSE;
}
// Allow external modules deny access to the Relationships tab for this node.
$access = (array) module_invoke_all('noderelationships_backref_access', $referred_node);
foreach ($access as $value) {
if ($value === FALSE) {
return FALSE;
}
}
// Ok, the user is allowed to view the node and this type has potential
// back references, so we can grant access to the relationships tab.
// @todo: Find out a way to hide the relationships tab if THIS node does
// not have real back references. The problem here is that a series of
// SELECT COUNT(*) queries would affect performance, so we would have to
// use a summary field or something similar. But this information would
// have to be updated when a nodereference is added, changed or removed
// from the database.
return TRUE;
}
/**
* Implementation of hook_views_api().
*/
function noderelationships_views_api() {
return array(
'api' => 2,
'path' => drupal_get_path('module', 'noderelationships') . '/views',
);
}
/**
* Implementation of hook_views_pre_view().
*
* @see noderelationships_backref_render_view()
*/
function noderelationships_views_pre_view(&$view, $display_id, &$view_args) {
// Apply custom configuration to the given view.
if ($view->tag == NODERELATIONSHIPS_BACKREF_VIEW_TAG) {
module_load_include('inc', 'noderelationships');
noderelationships_customize_backref_view($view, $display_id, $view_args);
}
elseif ($view->tag == NODERELATIONSHIPS_NODEREF_VIEW_TAG) {
module_load_include('inc', 'noderelationships');
noderelationships_customize_noderef_view($view, $display_id, $view_args);
}
}
/**
* Implementation of hook_views_pre_execute().
*
* @see noderelationships_customize_backref_view()
*/
function noderelationships_views_pre_execute(&$view) {
if (!empty($view->noderelationships_breadcrumb)) {
drupal_set_breadcrumb($view->noderelationships_breadcrumb);
}
}
/**
* Proxy function to preprocess the list views theme.
*/
function noderelationships_preprocess_views_ui_list_views(&$vars) {
if (!isset($vars['views']) || !is_array($vars['views'])) {
return;
}
foreach ($vars['views'] as $view) {
if (!empty($view->tag) && in_array($view->tag, array(
NODERELATIONSHIPS_BACKREF_VIEW_TAG,
NODERELATIONSHIPS_NODEREF_VIEW_TAG,
))) {
if (!empty($view->path)) {
$view->path = t('Dynamically generated by the Node Relationships module.');
}
$view->description = t('This view is dynamically customized by the Node Relationships module.') . '<br />' . $view->description;
}
}
}
/**
* Implementation of hook_field_info().
*
* Back reference fields:
* - Are single-valued fields and cannot be shared (per type storage is a must).
* This is why these fields are created automatically. Note that these fields
* are hidden from the "Add new field" and "Add existing field" selectors in
* the "Manage fields" screen. See _noderelationships_cck_admin_forms_alter().
* - Do not implement database columns and storage method is always per type.
* Hence, adding and removing back reference fields do not affect user data.
* - Do not provide CCK to Views integration for back reference fields.
* - Do not provide any widget in the node edit form.
* - The widget is defined to manage its own multiple values, therefore these
* fields cannot be added to multigroups.
* - Can be dragged from the "Manage fields" screen to any position in the node.
* - The widget label can be changed at will from the "Manage fields" screen.
* - The formatter simply renders a dynamically customized back reference view
* or the back references count.
*/
function noderelationships_field_info() {
return array(
'noderelationships_backref' => array(
'label' => t('Back reference'),
'description' => t('Display node back references.'),
),
);
}
/**
* Implementation of hook_field_settings().
*
* @see noderelationships_cck_backref_create()
* @see _noderelationships_cck_admin_forms_alter()
*/
function noderelationships_field_settings($op, $field) {
if ($op == 'save') {
return array(
'referrer_type',
'referrer_field',
);
}
elseif ($op == 'views data') {
return array();
}
}
/**
* Implementation of hook_field().
*/
function noderelationships_field($op, $node, $field, &$items, $teaser, $page) {
if ($op == 'load') {
// This is necessary so that we can use features such as
// content_view_field() invoked by Panels integration, etc.
return array(
$field['field_name'] => array(
NULL,
),
);
}
}
/**
* Implementation of hook_content_is_empty().
*/
function noderelationships_content_is_empty($item, $field) {
// Back reference fields are not stored in database, so tell CCK they are
// always empty.
return TRUE;
}
/**
* Implementation of hook_widget_info().
*/
function noderelationships_widget_info() {
return array(
'noderelationships_backref' => array(
'label' => t('Back reference'),
'field types' => array(
'noderelationships_backref',
),
'multiple values' => CONTENT_HANDLE_MODULE,
),
);
}
/**
* Implementation of hook_widget().
*/
function noderelationships_widget(&$form, &$form_state, $field, $items, $delta = NULL) {
// Back reference fields do not provide any widget in the node edit form.
return array();
}
/**
* Implementation of hook_field_formatter_info().
*
* @see theme_noderelationships_formatter_default()
*/
function noderelationships_field_formatter_info() {
return array(
'default' => array(
'label' => t('Back references view'),
'field types' => array(
'noderelationships_backref',
),
'multiple values' => CONTENT_HANDLE_MODULE,
),
'count' => array(
'label' => t('Back references count'),
'field types' => array(
'noderelationships_backref',
),
'multiple values' => CONTENT_HANDLE_MODULE,
),
);
}
/**
* Alter variables used for content-admin-field-overview-form.tpl.php.
*/
function noderelationships_preprocess_content_field_overview_form(&$vars) {
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.admin');
_noderelationships_preprocess_content_field_overview_form($vars);
}
/**
* Implementation of hook_content_extra_fields().
*/
function noderelationships_content_extra_fields($nodetype) {
$extra = array();
// Include common module functions.
module_load_include('inc', 'noderelationships');
// Obtain back reference settings for this type.
$backref_settings = noderelationships_settings_load($nodetype, 'backref');
$backref_regions = $backref_settings['regions'];
if (!empty($backref_regions[NODERELATIONSHIPS_BACKREF_REGION_PAGE])) {
$type_names = array();
foreach (array_keys($backref_regions[NODERELATIONSHIPS_BACKREF_REGION_PAGE]) as $relation_key) {
list($type_name, $field_name) = explode(':', $relation_key);
if (!isset($type_names[$type_name])) {
$type_names[$type_name] = noderelationships_get_localized_content_type_name($type_name);
}
}
// Sort types alphabetically.
uksort($type_names, '_noderelationships_sort_strncmp');
$extra['noderelationships'] = array(
'label' => t('Node relationships'),
'description' => t('Back reference views for the following types: @types.', array(
'@types' => implode(', ', $type_names),
)),
'weight' => noderelationships_get_element_weight($nodetype),
);
}
return $extra;
}
/**
* Implementation of hook_content_fieldapi().
*/
function noderelationships_content_fieldapi($op, $field) {
// Watch for changes in nodereference fields.
if ($op != 'read instance' && $field['type'] == 'nodereference') {
module_load_include('inc', 'noderelationships');
if ($op == 'delete instance') {
// Delete relations related to this field instance.
noderelationships_settings_delete_nodereference($field['type_name'], $field['field_name']);
}
// Clear cached information about relationships (all operations).
noderelationships_cache_clear();
}
}
/**
* Implementation of hook_node_type().
*/
function noderelationships_node_type($op, $info) {
module_load_include('inc', 'noderelationships');
if ($op == 'update') {
// Deal with content type name changes.
if (!empty($info->old_type) && $info->old_type != $info->type) {
noderelationships_settings_rename_type($info->old_type, $info->type);
}
}
elseif ($op == 'delete') {
// Delete relationship settings related to the content type being deleted.
noderelationships_settings_delete("type_name = '%s' OR related_type = '%s'", array(
$info->type,
$info->type,
));
}
// Clear cached information about relationships (all operations).
noderelationships_cache_clear();
}
/**
* Implementation of hook_nodeapi().
*/
function noderelationships_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if ($op == 'view') {
if (!$teaser && $page && $node->build_mode == NODE_BUILD_NORMAL) {
// Include common module functions.
module_load_include('inc', 'noderelationships');
// Obtain back reference settings for this type.
$backref_settings = noderelationships_settings_load($node->type, 'backref');
$backref_regions = $backref_settings['regions'];
// Process the node only if we have back reference settings for this region.
if (!empty($backref_regions[NODERELATIONSHIPS_BACKREF_REGION_PAGE])) {
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
_noderelationships_nodeapi_view($node, $backref_regions[NODERELATIONSHIPS_BACKREF_REGION_PAGE]);
}
}
}
elseif ($op == 'prepare translation') {
// Here we can assume translation module is enabled, translation for this
// content type is enabled and the current user is allowed to translate.
// Include common module functions.
module_load_include('inc', 'noderelationships');
// Obtain settings for nodereference extras for this type.
$noderef_settings = noderelationships_settings_load($node->type, 'noderef');
// Proceed only if the "Translate and reference" feature is enabled for
// any field in this content type.
if (!empty($noderef_settings['translate_and_reference'])) {
module_load_include('inc', 'noderelationships', 'noderelationships.translation');
_noderelationships_nodeapi_prepare_translation($node, $noderef_settings);
}
}
}
/**
* Implementation of hook_form_alter().
*/
function noderelationships_form_alter(&$form, $form_state, $form_id) {
// Alter CCK administration forms.
if (in_array($form_id, array(
'content_field_edit_form',
'content_field_overview_form',
))) {
// Delegate form manipulation to external script.
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.admin');
_noderelationships_cck_admin_forms_alter($form, $form_state, $form_id);
return;
}
// Alter views ui / settings forms.
if (strpos($form_id, 'views_ui_edit_') === 0 && isset($form_state['view']) && isset($form_state['view']->tag)) {
if ($form_state['view']->tag == NODERELATIONSHIPS_BACKREF_VIEW_TAG || $form_state['view']->tag == NODERELATIONSHIPS_NODEREF_VIEW_TAG) {
// Delegate form manipulation to external script.
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.admin');
_noderelationships_views_ui_form_alter($form, $form_state, $form_id, $form_state['view']->tag);
}
return;
}
// Alter views ui / clone view form.
if ($form_id == 'views_ui_add_form' && isset($form['tag'])) {
if ($form['tag']['#default_value'] == NODERELATIONSHIPS_BACKREF_VIEW_TAG || $form['tag']['#default_value'] == NODERELATIONSHIPS_NODEREF_VIEW_TAG) {
// Delegate form manipulation to external script.
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.admin');
_noderelationships_views_ui_form_alter($form, $form_state, $form_id, $form['tag']['#default_value']);
}
return;
}
// Alter admin theme settings form.
if ($form_id == 'system_admin_theme_settings') {
module_load_include('inc', 'noderelationships', 'noderelationships.admin');
_noderelationships_admin_theme_form_alter($form);
return;
}
// Alter node form.
if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] . '_node_form' == $form_id) {
$type_name = $form['#node']->type;
// Include common module functions.
module_load_include('inc', 'noderelationships');
// Obtain settings for nodereference extras for this type.
$noderef_settings = noderelationships_settings_load($type_name, 'noderef');
// Parent node processing only when we have settings for nodereference extras.
if (!empty($noderef_settings['search_and_reference_view']) || !empty($noderef_settings['create_and_reference']) || !empty($noderef_settings['translate_and_reference']) && noderelationships_translation_supported_type($type_name)) {
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
_noderelationships_parent_node_form_alter($form, $form_state, $type_name, $noderef_settings);
}
// Child node processing when the page request has been flagged to do so
// from noderelationships_noderef_page().
if (!empty($_GET['noderelationships_referrer_type']) && !empty($_GET['noderelationships_field_name'])) {
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
_noderelationships_child_node_form_alter($form, $_GET['noderelationships_referrer_type'], $_GET['noderelationships_field_name']);
}
elseif (!empty($_GET['noderelationships_edit'])) {
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
_noderelationships_child_edit_form_alter($form);
}
return;
}
}
/**
* Implementation of hook_init().
*
* @see noderelationships_noderef_page_create().
*/
function noderelationships_init() {
// Activate the admin theme if requested to.
if (arg(0) == 'noderelationships' && ($admin_theme = variable_get('admin_theme', '0')) != '0' && variable_get('noderelationships_admin_theme_children', '0')) {
$GLOBALS['custom_theme'] = $admin_theme;
}
// Enable the Modal Frame API for the child window.
if (!empty($_GET['noderelationships_referrer_type']) && !empty($_GET['noderelationships_field_name']) || !empty($_GET['noderelationships_edit'])) {
modalframe_child_js();
}
}
/**
* Proxy function to invoke node form after_build and pre_render callbacks,
* because the file where the real handler is implemented might not be included
* yet when the form is processed and invokes the callback.
*/
function _noderelationships_parent_node_form_scanner_proxy($form) {
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
return _noderelationships_parent_node_form_scanner($form);
}
/**
* Proxy function to invoke the pre_render callback for the child node form.
*/
function _noderelationships_child_node_form_pre_render_proxy($form) {
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
return _noderelationships_child_node_form_pre_render($form);
}
/**
* Proxy function to invoke the submit handler for the child node form.
*/
function _noderelationships_child_node_form_submit_proxy($form, &$form_state) {
module_load_include('inc', 'noderelationships');
module_load_include('inc', 'noderelationships', 'noderelationships.pages');
_noderelationships_child_node_form_submit($form, $form_state);
}
Functions
Name![]() |
Description |
---|---|
noderelationships_backref_access | Access callback for the node relationships tab. |
noderelationships_content_extra_fields | Implementation of hook_content_extra_fields(). |
noderelationships_content_fieldapi | Implementation of hook_content_fieldapi(). |
noderelationships_content_is_empty | Implementation of hook_content_is_empty(). |
noderelationships_field | Implementation of hook_field(). |
noderelationships_field_formatter_info | Implementation of hook_field_formatter_info(). |
noderelationships_field_info | Implementation of hook_field_info(). |
noderelationships_field_settings | Implementation of hook_field_settings(). |
noderelationships_form_alter | Implementation of hook_form_alter(). |
noderelationships_init | Implementation of hook_init(). |
noderelationships_menu | Implementation of hook_menu(). |
noderelationships_nodeapi | Implementation of hook_nodeapi(). |
noderelationships_node_type | Implementation of hook_node_type(). |
noderelationships_preprocess_content_field_overview_form | Alter variables used for content-admin-field-overview-form.tpl.php. |
noderelationships_preprocess_views_ui_list_views | Proxy function to preprocess the list views theme. |
noderelationships_theme | Implementation of hook_theme(). |
noderelationships_views_api | Implementation of hook_views_api(). |
noderelationships_views_pre_execute | Implementation of hook_views_pre_execute(). |
noderelationships_views_pre_view | Implementation of hook_views_pre_view(). |
noderelationships_widget | Implementation of hook_widget(). |
noderelationships_widget_info | Implementation of hook_widget_info(). |
_noderelationships_child_node_form_pre_render_proxy | Proxy function to invoke the pre_render callback for the child node form. |
_noderelationships_child_node_form_submit_proxy | Proxy function to invoke the submit handler for the child node form. |
_noderelationships_parent_node_form_scanner_proxy | Proxy function to invoke node form after_build and pre_render callbacks, because the file where the real handler is implemented might not be included yet when the form is processed and invokes the callback. |