You are here

relation_class.module in Subform 5

CRUD, and manage relation_classes and relation_class lists

File

relation_class.module
View source
<?php

/**
 * @file
 * CRUD, and manage relation_classes and relation_class lists
 */

/**
 * Implementation of hook_help()
 * Display help text for the relation_class module
 */
function relation_class_help($section) {
  switch ($section) {
    case 'admin/help#relation_class':
      $o .= '<p>' . t('CRUD, and manage relation_classes and relation_class lists.') . '</p>';
      return $o;
    case 'node/add#relation_class':
      return t('Defines a type of relationship that can exist between nodes.');
  }
}

/**
 * Implementation of hook_perm().
 * Define the permissions this module uses
 */
function relation_class_perm() {
  return array(
    'create relation_class items',
    'manage relation_class items',
  );
}

/**
 * Implementation of hook_access().
 */
function relation_class_access($op, $node) {
  global $user;
  if ($op == 'create') {
    return user_access('create relation_class items');
  }
  if ($op == 'update' || $op == 'delete') {
    if (user_access('manage relation_class items')) {
      return TRUE;
    }
  }
}

/**
 * Implementation of hook_menu().
 */
function relation_class_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'title' => t('relation_class'),
      'path' => 'node/add/relation_class',
      'access' => user_access('create relation_class items'),
    );
    $items[] = array(
      'title' => t('manage relation classes'),
      'path' => 'node/manage/relation_class',
      'access' => user_access('manage relation_class items'),
      'callback' => '_manage_relation_classes',
    );
  }
  return $items;
}

/**
 * Implementation of hook_node_info().
 * Define the node type
 */
function relation_class_node_info() {
  return array(
    'relation_class' => array(
      'name' => t('relation class'),
      'base' => 'relation_class',
      'module' => 'relation_class',
    ),
  );
}

/**
 * hook_form
 */
function relation_class_form(&$node) {
  drupal_set_html_head(theme('stylesheet_import', base_path() . drupal_get_path('module', 'subform') . '/subform.css'), "module");
  drupal_set_html_head(theme('stylesheet_import', base_path() . drupal_get_path('module', 'subform') . '/relation_class.css'), "module");
  $form = array(
    'title' => array(
      '#type' => 'textfield',
      '#title' => t('Title'),
      '#required' => TRUE,
      '#default_value' => $node->title,
      '#weight' => -5,
    ),
    'sides' => array(
      '#type' => 'fapi_table',
      'rows' => array(
        array(
          // first row
          array(
            // first cell
            'left_node_type' => array(
              '#type' => 'select',
              '#title' => t('Node Type'),
              '#default_value' => $node->left_node_type,
              '#options' => node_get_types(),
              '#required' => TRUE,
            ),
          ),
          array(
            // second cell
            'right_node_type' => array(
              '#type' => 'select',
              '#title' => t('Node Type'),
              '#default_value' => $node->right_node_type,
              '#options' => node_get_types(),
              '#required' => TRUE,
            ),
          ),
        ),
        array(
          // second row
          array(
            // first cell
            'left_node_cardinality' => array(
              '#type' => 'textfield',
              '#title' => t('Cardinality'),
              '#default_value' => $node->left_node_cardinality,
              '#required' => TRUE,
            ),
          ),
          array(
            // second cell
            'right_node_cardinality' => array(
              '#type' => 'textfield',
              '#title' => t('Cardinality'),
              '#default_value' => $node->right_node_cardinality,
              '#required' => TRUE,
            ),
          ),
        ),
        array(
          // third row
          array(
            // first cell
            'unique_instances' => array(
              '#type' => 'checkbox',
              '#title' => 'Prevent duplicate relation instances?',
              '#default_value' => isset($node->unique_instances) ? $node->unique_instances : true,
            ),
          ),
          array(),
        ),
      ),
    ),
  );
  return $form;
}

/**
 * Implementation of hook_view, add our node specific information
 * @param node object to display
 * @param boolean is this a teaser or full node?
 * @param boolean is this displaying on its own page
 */
function relation_class_view(&$node, $teaser = FALSE, $page = FALSE) {
  $node = node_prepare($node, $teaser);
  $node->body = theme('relation_class_view', $node);
}

/**
 * Theme function to display additional node data
 * @param node to display
 * @return HTML string with additional node information
 */
function theme_relation_class_view($node) {
  $output = '<div class="relation_class_view">';
  $output .= "<pre>{$node->title} : {$node->left_node_type}({$node->left_node_cardinality}) <-> {$node->right_node_type}({$node->right_node_cardinality})" . ($node->unique_instances ? "Unique" : "") . "</pre>";
  $output .= '</div>';
  return $output;
}

/**
 * Validate our forms
 * @param string form id
 * @param array form values
 */
function relation_class_validate($form_id, $form_values) {

  // drupal_set_message( '<pre>' . print_r( $form_values, true ) . '</pre>' );
  if (!is_numeric($form_values['sides']['rows'][1][0]['left_node_cardinality']['#value'])) {
    form_set_error('left_node_cardinality', t('Left Node Cardinality must be an integer.'));
  }
  else {
    $form_values['sides']['rows'][1][0]['left_node_cardinality']['#value'] = intval($form_values['left_node_cardinality']['#value']);
  }
  if (!is_numeric($form_values['sides']['rows'][1][1]['right_node_cardinality']['#value'])) {
    form_set_error('right_node_cardinality', t('Right Node Cardinality must be an integer.'));
  }
  else {
    $form_values['sides']['rows'][1][1]['right_node_cardinality']['#value'] = intval($form_values['left_node_cardinality']['#value']);
  }
}
function relation_class_insert($node) {
  db_query("\n  INSERT INTO\n    {relation_class}\n    (nid, vid, left_node_type, left_node_cardinality, right_node_type, right_node_cardinality, unique_instances)\n  VALUES\n    ({$node->nid}, {$node->vid}, '{$node->left_node_type}', {$node->left_node_cardinality}, '{$node->right_node_type}', {$node->right_node_cardinality}, {$node->unique_instances})");
}
function relation_class_list() {
  $relation_class_results = db_query("SELECT nid, title FROM {node} WHERE type = 'relation_class' ORDER BY title");
  $relation_classes = array();
  while ($relation_class = db_fetch_object($relation_class_results)) {
    $relation_classes[$relation_class->nid] = $relation_class->title;
  }
  return $relation_classes;
}
function relation_class_extended_list() {
  $relation_class_results = db_query("SELECT {node}.nid, {node}.title, {relation_class}.left_node_type, {relation_class}.left_node_cardinality, {relation_class}.right_node_type, {relation_class}.right_node_cardinality FROM {node} INNER JOIN {relation_class} ON {node}.nid = {relation_class}.nid AND {node}.vid = {relation_class}.vid WHERE type = 'relation_class' ORDER BY title");
  $relation_classes = array();
  while ($relation_class = db_fetch_object($relation_class_results)) {
    $relation_classes[$relation_class->nid] = "{$relation_class->title} : {$relation_class->left_node_type}({$relation_class->left_node_cardinality}) <-> {$relation_class->right_node_type}({$relation_class->right_node_cardinality})";
  }
  return $relation_classes;
}

/**
 * Implemenation of hook_load
 * @param node object to load additional information for
 * @return object with todo fields
 */
function relation_class_load($node) {
  return db_fetch_object(db_query("SELECT left_node_type, left_node_cardinality, right_node_type, right_node_cardinality, unique_instances FROM {relation_class} WHERE nid = %d AND vid = %d", $node->nid, $node->vid));
}

/**
 * hook_update, saves changes
 * @param node object
 */
function relation_class_update($node) {
  db_query("\n    UPDATE\n      {relation_class}\n    SET\n      left_node_type = '{$node->left_node_type}',\n      left_node_cardinality = {$node->left_node_cardinality},\n      right_node_type = '{$node->right_node_type}',\n      right_node_cardinality = {$node->right_node_cardinality},\n      unique_instances = {$node->unique_instances}\n    WHERE\n      nid = {$node->nid}\n        AND\n      vid = {$node->vid}");
}
function _manage_relation_classes() {
  drupal_set_html_head(theme('stylesheet_import', base_path() . drupal_get_path('module', 'subform') . '/subform.css'), "module");
  drupal_set_html_head(theme('stylesheet_import', base_path() . drupal_get_path('module', 'subform') . '/manage_relation_classes.css'), "module");
  $relation_class_results = db_query("\n    SELECT\n      *\n    FROM\n      {relation_class}\n      INNER JOIN\n      {node}\n        ON\n        {relation_class}.nid = {node}.nid\n          AND\n        {relation_class}.vid = {node}.vid\n  ");
  drupal_add_js(drupal_get_path('module', 'subform') . '/iframe_resize.js', "module");
  $output = "";
  while ($relation_class = db_fetch_object($relation_class_results)) {
    $output[] = "\n<div class='iframe_div'><iframe\n  class='subform_iframe'\n  src='" . check_url(url("subform/{$relation_class->nid}/edit", NULL, NULL, TRUE)) . "'\n  onload='resizeIFrame(this);'>\n</IFRAME></div>";
  }
  $new = "\n\n<script>\n\nfunction newRelationClass() {\n\n  var table = document.getElementById('relation_classes_table');\n\n  var row = table.insertRow( table.rows.length );\n  var cell = row.insertCell(0);\n  cell.innerHTML += '<div class=\\'iframe_div\\'><iframe class=\\'subform_iframe\\' src=\\'" . check_url(url('subform/add/relation_class', NULL, NULL, TRUE)) . "\\' onload=\\'resizeIFrame(this);\\'></iframe></div>';\n\n}\n\n</script>\n<br />\n<a href='#' onClick='newRelationClass(); return false;'>New</a>\n\n";
  $output = "<table width=100% id=\"relation_classes_table\"><tr><td>" . ($output ? implode("</td></tr><tr><td>", $output) : "") . "</td></tr></table>{$new}";
  $form = array(
    'relation_classes' => array(
      '#type' => 'markup',
      '#value' => $output,
    ),
  );
  return drupal_get_form('_manage_relation_classes', $form);
}
function relation_instance_load($relation_instance_id) {
  return db_fetch_object(db_query("SELECT * FROM {relation_instance} WHERE id = %d", $relation_instance_id));
}
function relation_instance_delete($relation_instance_id) {
  db_query("DELETE FROM {relation_instance} WHERE id = %d", $relation_instance_id);
  return "deleted";
}
function relation_instance_update($old_parent_node, $parent_node) {
  db_query("\n    UPDATE\n      {relation_instance}\n    SET\n      left_node = {$parent_node}\n    WHERE left_node = {$old_parent_node}");
  db_query("\n    UPDATE\n      {relation_instance}\n    SET\n      right_node = {$parent_node}\n    WHERE right_node = {$old_parent_node}");
}
function relation_instance_insert($node) {
  relation_instance_trim_stale();
  $relation_class = node_load($node->relation_class);
  if ($relation_class->unique_instances) {
    if ($id = db_result(db_query("SELECT id FROM {relation_instance} WHERE relation_class = %d AND left_node = %d AND right_node = %d", $node->relation_class, $node->left_node, $node->right_node))) {
      return $id;
    }
  }
  db_query("\n  INSERT INTO\n    {relation_instance}\n    (relation_class, left_node, right_node, timestamp)\n  VALUES\n    ({$node->relation_class}, {$node->left_node}, {$node->right_node}, " . strtotime("now") . ")");
  return db_result(db_query("SELECT LAST_INSERT_ID()"));
}
function relation_instance_selectables_query($relation_class, $child_side, $parent_node) {
  $relation_class_node = node_load($relation_class);
  $child_side_node = $child_side . "_node";
  $child_side_node_type = $child_side . "_node_type";
  $child_side_node_type = $relation_class_node->{$child_side_node_type};
  $child_side_cardinality = $child_side . "_node_cardinality";
  $child_side_cardinality = $relation_class_node->{$child_side_cardinality};
  $parent_side = $child_side == "left" ? "right" : "left";
  $parent_side_node = $parent_side . "_node";
  $duplicate_relation_cost = $relation_class_node->unique_instances ? $child_side_cardinality : 1;
  $sql = "\nSELECT\n  nid, SUM(related) as related_count\nFROM\n(\n  SELECT\n    nid, IF(relation_class IS NULL, 0, IF({$parent_side_node} <= 0, IF({$parent_side_node} = {$parent_node}, {$duplicate_relation_cost}, 0), IF({$parent_side_node} = {$parent_node}, {$duplicate_relation_cost}, 1))) as related\n  FROM\n    node\n      LEFT JOIN\n    relation_instance ON node.nid = relation_instance.{$child_side_node}\n  WHERE\n    node.type = '{$child_side_node_type}'\n      AND\n    (\n      relation_class IS NULL\n        OR\n      relation_class = {$relation_class}\n    )\n) as possibilities\nGROUP BY\n  nid\nHAVING\n  related_count < {$child_side_cardinality}\n  ";

  // drupal_set_message( $sql );
  return $sql;
}
function relation_instance_used_slots($relation_class, $parent_side_node, $child_side_node, $parent_node) {
  return db_result(db_query("SELECT\n        COUNT({$child_side_node})\n      FROM\n        {relation_instance}\n      WHERE\n        relation_class = %d\n          AND\n        {$parent_side_node} = %d", $relation_class, $parent_node));
}
function relation_instance_trim_stale() {
  db_query("DELETE\n      FROM\n        {relation_instance}\n      WHERE\n        (left_node < 0\n          OR\n        right_node < 0)\n          AND\n        timestamp <= %d", strtotime("now") - 24 * 60 * 60);
}

Functions

Namesort descending Description
relation_class_access Implementation of hook_access().
relation_class_extended_list
relation_class_form hook_form
relation_class_help Implementation of hook_help() Display help text for the relation_class module
relation_class_insert
relation_class_list
relation_class_load Implemenation of hook_load
relation_class_menu Implementation of hook_menu().
relation_class_node_info Implementation of hook_node_info(). Define the node type
relation_class_perm Implementation of hook_perm(). Define the permissions this module uses
relation_class_update hook_update, saves changes
relation_class_validate Validate our forms
relation_class_view Implementation of hook_view, add our node specific information
relation_instance_delete
relation_instance_insert
relation_instance_load
relation_instance_selectables_query
relation_instance_trim_stale
relation_instance_update
relation_instance_used_slots
theme_relation_class_view Theme function to display additional node data
_manage_relation_classes