array( // ##### -- Added: t() /elfur #######/ 'title' => t('Node 2 Node administration'), // ##### -- Added: t() /elfur #######/ 'description' => t('Settings for the Node 2 Node module'), 'page callback' => 'drupal_get_form', 'page arguments' => array('node2node_admin'), 'access arguments' => array('administer node2node'), 'type' => MENU_NORMAL_ITEM, ), ); } /** * Adminstration form */ function node2node_admin() { // get a list of node types $nodelist = array('' => ''); $res = db_query('SELECT type, name FROM {node_type} ORDER BY name'); while ($row = db_fetch_array($res)) { $nodelist[$row['type']] = $row['name']; } // how many relationships are there? $numrels = variable_get('node2node_relationships_count', 0); $numrows = $numrels + 3; for ($i = 0; $i < $numrels + NODE2NODE_EXTRA_ROWS; $i++) { $form['relationship'.$i] = array( // ##### -- Added: t() and splitted up the quote, to leave the space out of the translation string /elfur #######/ '#title' => t('Relationship').' '.($i + 1), '#type' => 'fieldset', ); $form['relationship'.$i]['node2node_parent'.$i] = array( // ##### -- Added: t() /elfur #######/ '#title' => t('Parent'), '#type' => 'select', '#options' => $nodelist, '#default_value' => variable_get('node2node_parent'.$i, ''), '#prefix' => '', ); $form['relationship'.$i]['node2node_name'.$i] = array( // ##### -- Added: t() /elfur #######/ '#title' => t('Name of relationship'), '#type' => 'textfield', '#default_value' => variable_get('node2node_name'.$i, 'has'), '#size' => 30, '#prefix' => '', ); $form['relationship'.$i]['node2node_child'.$i] = array( // ##### -- Added: t() /elfur #######/ '#title' => t('Child'), '#type' => 'select', '#options' => $nodelist, '#default_value' => variable_get('node2node_child'.$i, ''), '#prefix' => '', ); $form['relationship'.$i]['node2node_id'.$i] = array( // ##### -- Added: t() /elfur #######/ '#title' => t('ID'), '#type' => 'textfield', '#default_value' => variable_get('node2node_id'.$i, 'rel_'.$i), '#size' => 10, '#maxlength' => 10, '#prefix' => '
', // ##### -- Added: The whole line, for (X)HTML validation /elfur #######/ '#suffix' => '', ); $form['relationship'.$i]['node2node_iname'.$i] = array( // ##### -- Added: t() /elfur #######/ '#title' => t('Inverse name'), '#type' => 'textfield', '#default_value' => variable_get('node2node_iname'.$i, 'belongs to'), '#size' => 30, // ##### -- Added: The whole line, for (X)HTML validation /elfur #######/ '#suffix' => '', // ##### -- Added: The whole line, for (X)HTML validation /elfur #######/ '#suffix' => '', '#suffix' => '
', ); } $form['terminology'] = array( // ##### -- Added: t() /elfur #######/ '#title' => t('Terminology'), '#type' => 'fieldset', ); $form['terminology']['node2node_parentlinks'] = array( // ##### -- Added: t()l -- changed order of title and type, to be the same sequence as all other definitions above. /elfur #######/ '#title' => t('Parent links'), '#type' => 'textfield', '#default_value' => variable_get('node2node_parentlinks', 'Parent links'), ); $form['terminology']['node2node_childlinks'] = array( // ##### -- Added: t()l -- changed order of title and type, to be the same sequence as all other definitions above. /elfur #######/ '#title' => t('Child links'), '#type' => 'textfield', '#default_value' => variable_get('node2node_childlinks', 'Child links'), ); $form['node2node_relationships_count'] = array( '#type' => 'hidden', '#value' => $numrels, ); return system_settings_form($form); } function node2node_admin_validate(&$form, &$form_state) { $error = false; $numrows = $form_state['values']['node2node_relationships_count']; $duplist = array(); // validation pass for ($i = 0; $i < ($numrows + NODE2NODE_EXTRA_ROWS); $i++) { $parent = $form_state['values']['node2node_parent'.$i]; $name = $form_state['values']['node2node_name'.$i]; $iname = $form_state['values']['node2node_iname'.$i]; $child = $form_state['values']['node2node_child'.$i]; $id = $form_state['values']['node2node_id'.$i]; if ($parent != '') { if ($child == '') { form_set_error('node2node_child'.$i, t('Child node must be defined')); $error = true; } if ($id == '') { form_set_error('node2node_id'.$i, t('ID must be defined')); $error = true; } $dupkey = $parent . '||'.$name.'||' . $child; if (isset($duplist[$dupkey])) { form_set_error('node2node_parent'.$i, t('Duplicated relationship')); $error = true; } else { $duplist[$dupkey] = ''; } $dupkey = '^^^' . $id; if (isset($duplist[$dupkey])) { form_set_error('node2node_id'.$i, t('Duplicated ID')); $error = true; } else { $duplist[$dupkey] = ''; } } } // if valid, modify the rows if (!$error) { $count = -1; // count the number of valid rows for ($i = 0; $i < ($numrows + NODE2NODE_EXTRA_ROWS); $i++) { $parent = $form_state['values']['node2node_parent'.$i]; $name = $form_state['values']['node2node_name'.$i]; $iname = $form_state['values']['node2node_iname'.$i]; $child = $form_state['values']['node2node_child'.$i]; $id = $form_state['values']['node2node_id'.$i]; if ($parent != '') { $count++; // shift the row upwards if necessary if ($i != $count) { $form_state['values']['node2node_parent'.$count] = $parent; $form_state['values']['node2node_name'.$count] = $name; $form_state['values']['node2node_iname'.$count] = $iname; $form_state['values']['node2node_child'.$count] = $child; $form_state['values']['node2node_id'.$count] = $id; $form_state['values']['node2node_parent'.$i] = ''; $form_state['values']['node2node_name'.$i] = ''; $form_state['values']['node2node_iname'.$i] = ''; $form_state['values']['node2node_child'.$i] = ''; $form_state['values']['node2node_id'.$i] = ''; } } else { } } $form_state['values']['node2node_relationships_count'] = $count + 1; // remove additional settings for ($i = $count + 1; $i < ($numrows + NODE2NODE_EXTRA_ROWS); $i++) { variable_del('node2node_parent'.$i); variable_del('node2node_name'.$i); variable_del('node2node_child'.$i); unset($form_state['values']['node2node_parent'.$i]); unset($form_state['values']['node2node_name'.$i]); unset($form_state['values']['node2node_iname'.$i]); unset($form_state['values']['node2node_child'.$i]); unset($form_state['values']['node2node_id'.$i]); } } } /** * Returns a list of relationship types * * Returns: * List of IDs by parent * List of IDs by child * Array of information by ID */ function node2node_reltypes() { static $reltypes; if (!isset($reltypes)) { $numrels = variable_get('node2node_relationships_count', 0); $reltypes = array(); for ($i = 0; $i < $numrels; $i++) { $parent = variable_get('node2node_parent'.$i, ''); $name = variable_get('node2node_name'.$i, ''); $iname = variable_get('node2node_iname'.$i, ''); $child = variable_get('node2node_child'.$i, ''); $id = variable_get('node2node_id'.$i, ''); $reltypes['parent'][$parent][$id] = ''; $reltypes['child'][$child][$id] = ''; $reltypes['id'][$id] = array( 'parent' => $parent, 'name' => $name, 'iname' => $iname, 'child' => $child, ); } } return $reltypes; } /** * Implementation of hook_nodeapi */ function node2node_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { $type = $node->type; $reltypes = node2node_reltypes(); switch ($op) { case 'load': // get child nodes $child_nodes = array(); $res = db_query("SELECT nn.seq, nn.type, nn.child_nid, n.title, n.type AS node_type FROM {node2node} nn LEFT JOIN {node} n ON nn.child_nid=n.nid WHERE nn.parent_nid=%d ORDER BY nn.seq", $node->nid); while ($row = db_fetch_array($res)) { $nid = $row['child_nid']; // to do - put a node access check in here $child_nodes[$row['seq']] = $row; $child_nodes[$row['seq']]['name'] = $reltypes['id'][$row['type']]['name']; $child_nodes[$row['seq']]['iname'] = $reltypes['id'][$row['type']]['iname']; } $node->child_nodes = $child_nodes; // get parent nodes $parent_nodes = array(); $res = db_query("SELECT nn.seq, nn.type, nn.parent_nid, n.title, n.type AS node_type FROM {node2node} nn LEFT JOIN {node} n ON nn.parent_nid=n.nid WHERE nn.child_nid=%d ORDER BY nn.parent_nid", $node->nid); while ($row = db_fetch_array($res)) { $nid = $row['parent_nid']; // to do - put a node access check in here $parent_nodes[$row['parent_nid']] = $row; $parent_nodes[$row['parent_nid']]['name'] = $reltypes['id'][$row['type']]['name']; $parent_nodes[$row['parent_nid']]['iname'] = $reltypes['id'][$row['type']]['iname']; } $node->parent_nodes = $parent_nodes; break; case 'view': $content = ''; $teaser = $a3; if (!$teaser) { if (count($node->parent_nodes)) { $content .= '

'.t(variable_get('node2node_parentlinks', 'Parent links')).'

'; foreach ($node->parent_nodes as $pnode) { // $content .= l($pnode['title'],'node/'.$pnode['parent_nid']) . ' (' . $pnode['node_type'] . ') ' . $pnode['name'] . ' ' . $node->title.'
'; $content .= t('This') . ' ' . $node->type . ' ' . $pnode['iname'] . ' ' . $pnode['node_type'] . ' ' . l($pnode['title'],'node/'.$pnode['parent_nid']) . '
'; } $content .= '
'; } if (count($node->child_nodes)) { $content .= '

'.t(variable_get('node2node_childlinks', 'Child links')).'

'; foreach ($node->child_nodes as $cnode) { // $content .= $node->title . ' ' . $cnode['name'] . ' ' . l($cnode['title'], 'node/'.$cnode['child_nid']) . ' (' . $cnode['node_type'] . ')
'; $content .= t('This') . ' ' . $node->type . ' ' . $cnode['name'] . ' ' . $cnode['node_type'] . ' ' . l($cnode['title'], 'node/'.$cnode['child_nid']) . '
'; } $content .= '
'; } if (node_access('update',$node)) { $content .= '

'.t('Link target').'

' . drupal_get_form('node2node_make_target'); } $node->content['node2node']['#value'] = $content; $node->content['node2node']['#weight'] = 10; } break; case 'insert': case 'update': $order = array(); // go through links array (prepared in node2node_form_submit) if (!isset($node->links)) {$node->links = array();} foreach ($node->links as $pc=>$vpc) { foreach ($vpc as $key=>$value) { switch ($pc) { case 'p': $checked = $value['checked']; $pnid = $value['pnid']; $pseq = $value['pseq']; $porig = $value['porig']; $ptype = $value['ptype']; // delete a parent if ($porig && !$checked) { db_query("DELETE FROM {node2node} WHERE parent_nid=%d AND type='%s' AND child_nid=%d", $pnid, $ptype, $node->nid); } // add a parent if (!$porig && $checked) { $seq = 0; $res = db_query("SELECT MAX(seq) AS seq FROM {node2node} WHERE parent_nid=%d", $pnid); $ret = db_fetch_array($res); $seq = $ret['seq'] + 1; db_query("INSERT INTO {node2node} (parent_nid, seq, type, child_nid) VALUES (%d, %d, '%s', %d)", $pnid, $seq, $ptype, $node->nid); } break; case 'c': $checked = $value['checked']; $cnid = $value['cnid']; $cseq = $value['cseq']; $corig = $value['corig']; $ctype = $value['ctype']; // delete a child if ($corig && !$checked) { db_query("DELETE FROM {node2node} WHERE child_nid=%d AND type='%s' AND parent_nid=%d", $cnid, $ctype, $node->nid); } // insert a child if (!$corig && $checked) { $seq = 0; $res = db_query("SELECT MAX(seq) AS seq FROM {node2node} WHERE parent_nid=%d", $node->nid); $ret = db_fetch_array($res); $seq = $ret['seq'] + 1; db_query("INSERT INTO {node2node} (parent_nid, seq, type, child_nid) VALUES (%d, %d, '%s', %d)", $node->nid, $seq, $ctype, $cnid); } // set order for checked children if ($checked) { $order[$cseq][] = $ctype.'^^^'.$cnid; } break; } } } // update the order of children $i = 0; db_query("UPDATE {node2node} SET seq=seq+10000 WHERE parent_nid=%d", $node->nid); ksort($order, SORT_NUMERIC); foreach ($order as $seq=>$value) { foreach ($value as $seq1=>$value1) { $keys = explode('^^^', $value1); $type = $keys[0]; $cnid = $keys[1]; $i++; db_query("UPDATE {node2node} SET seq=%d WHERE parent_nid=%d AND type='%s' AND child_nid=%d", $i, $node->nid, $type, $cnid); } } break; case 'delete': // delete all relationships connected with this node db_query("DELETE FROM {node2node} WHERE parent_nid=%d OR child_nid=%d", $node->nid, $node->nid); } } /** * Form to set this node as target */ function node2node_make_target() { $nid = arg(1); if ($nid != $_SESSION['node2node']['nid']) { $form['desc'] = array( // ##### -- Changed: Removed space ' ' from within the t() and added it at the end. /elfur #######/ '#value' => t('Set this node to be the target node so that other nodes can be associated with it.').' ', ); $form['maketarget'] = array ( '#type' => 'submit', // ##### -- Added: t() /elfur #######/ '#value' => t('Make target'), ); } else { $form['desc'] = array( '#value' => t('This node is the current target - when editing other nodes, you can associate them with this one.'), ); } return $form; } function node2node_make_target_submit() { $nid = arg(1); $node = node_load($nid); $_SESSION['node2node']['nid'] = $nid; $_SESSION['node2node']['type'] = $node->type; $_SESSION['node2node']['title'] = $node->title; } /** * Implementation of hook_form */ function node2node_form_alter(&$form, $form_state, $form_id) { // get node information $node = $form['#node']; $nid = $node->nid; $type = $node->type; // flag to say we have modded the form $modded = false; // get the list of relationship types $reltypes = node2node_reltypes(); // index the parent and child nodes to avoid adding twice $ind = array(); if (isset($node->parent_nodes)) { foreach ($node->parent_nodes as $k=>$pnode) { $ind[$pnode['type']][$pnode['parent_nid']] = ''; } } if (isset($node->child_nodes)) { foreach ($node->child_nodes as $k=>$cnode) { $ind[$cnode['type']][$cnode['child_nid']] = ''; } } // list of possible parent relationships $pp = array(); if ($nid != $_SESSION['node2node']['nid']) { foreach ($reltypes['id'] as $id=>$rel) { if ($rel['parent'] == $_SESSION['node2node']['type'] && $rel['child'] == $node->type && !isset($ind[$id][$_SESSION['node2node']['nid']])) { $node->parent_nodes[] = array( 'seq' => '', 'type' => $id, 'parent_nid' => $_SESSION['node2node']['nid'], 'title' => $_SESSION['node2node']['title'], 'node_type' => $_SESSION['node2node']['type'], 'name' => $rel['name'], 'potential' => true, ); } elseif ($rel['child'] == $_SESSION['node2node']['type'] && $rel['parent'] == $node->type && !isset($ind[$id][$_SESSION['node2node']['nid']])) { $node->child_nodes[] = array( 'seq' => '', 'type' => $id, 'child_nid' => $_SESSION['node2node']['nid'], 'title' => $_SESSION['node2node']['title'], 'node_type' => $_SESSION['node2node']['type'], 'name' => $rel['name'], 'potential' => true, ); } } } // list the parent nodes if (count($node->parent_nodes)) { $modded = true; $form['node2nodeparents'] = array( '#type' => 'fieldset', '#collapsible' => true, '#title' => t('This node is a child of the checked nodes (uncheck to remove, check to add):'), ); $form['node2nodeparents'][] = array( // ##### -- Added: 's, for (X)HTML validation /elfur #######/ '#value' => '', ); $i = 0; foreach ($node->parent_nodes as $k=>$pnode) { $form['node2nodeparents']['p_'.$i] = array( '#type' => 'hidden', '#value' => $i, ); $form['node2nodeparents'][] = array( '#prefix' => '', ); $form['node2nodeparents'][] = array( '#prefix' => '', ); $form['node2nodeparents'][] = array( '#prefix' => '', ); $form['node2nodeparents'][] = array( '#prefix' => '', ); $form['node2nodeparents']['pcheck_'.$i] = array( '#prefix' => '', ); $form['node2nodeparents']['pnid_'.$i] = array( '#type' => 'hidden', '#value' => $pnode['parent_nid'], ); $form['node2nodeparents']['pseq_'.$i] = array( '#type' => 'hidden', '#value' => $pnode['seq'], ); $form['node2nodeparents']['porig_'.$i] = array( '#type' => 'hidden', '#value' => !isset($pnode['potential']), ); $form['node2nodeparents']['ptype_'.$i] = array( '#type' => 'hidden', '#value' => $pnode['type'], ); $i++; } $form['node2nodeparents'][] = array( '#value' => '
'.t('Parent node').''.t('Type').''.t('Relationship').''.t('This node').''.t('Check').'
', '#value' => $pnode['title'], '#suffix' => '', '#value' => $pnode['node_type'], '#suffix' => '', '#value' => $pnode['name'], '#suffix' => '', '#value' => $node->title, '#suffix' => '', '#type' => 'checkbox', '#default_value' => !isset($pnode['potential']), '#suffix' => '
', ); } // list the child nodes if (count($node->child_nodes)) { $modded = true; $form['node2nodechildren'] = array( '#type' => 'fieldset', '#collapsible' => true, '#title' => t('This node is a parent of the checked nodes (uncheck to remove, check to add):'), ); $form['node2nodechildren'][] = array( // ##### -- Added: 's, for (X)HTML validation /elfur #######/ '#value' => '', ); $i = 0; foreach ($node->child_nodes as $k=>$cnode) { $form['node2nodechildren']['c_'.$i] = array( '#type' => 'hidden', '#value' => $i, ); $form['node2nodechildren']['cseq_'.$i] = array( '#prefix' => '', ); $form['node2nodechildren'][] = array( '#prefix' => '', ); $form['node2nodechildren'][] = array( '#prefix' => '', ); $form['node2nodechildren'][] = array( '#prefix' => '', ); $form['node2nodechildren'][] = array( '#prefix' => '', ); $form['node2nodechildren']['ccheck_'.$i] = array( '#prefix' => '', ); $form['node2nodechildren']['cnid_'.$i] = array( '#type' => 'hidden', '#value' => $cnode['child_nid'], ); $form['node2nodechildren']['corig_'.$i] = array( '#type' => 'hidden', '#value' => !isset($cnode['potential']), ); $form['node2nodechildren']['ctype_'.$i] = array( '#type' => 'hidden', '#value' => $cnode['type'], ); $i++; } $form['node2nodechildren'][] = array( '#value' => '
'.t('Sequence').''.t('This node').''.t('Relationship').''.t('Child node').''.t('Type').''.t('Check').'
', '#type' => 'weight', '#delta' => 100, '#default_value' => $i, //$cnode['seq'], '#suffix' => '', '#value' => $node->title, '#suffix' => '', '#value' => $cnode['name'], '#suffix' => '', '#value' => $cnode['title'], '#suffix' => '', '#value' => $cnode['node_type'], '#suffix' => '', '#type' => 'checkbox', '#default_value' => !isset($cnode['potential']), '#suffix' => '
', ); } // add the submit function if ($modded) { $form['#submit'][] = 'node2node_form_submit'; } } /* Handle submission of the form data */ function node2node_form_submit(&$form, &$form_state) { // collects the form data into a cleaned up array to be used by node2node_nodeapi $links = array(); $node = $form['#node']; $order = array(); foreach ($form_state['values'] as $key=>$value) { switch (substr($key,0,2)) { case 'p_': $links['p'][] = array( 'checked' => $form_state['values']['pcheck_'.$value], 'pnid' => $form_state['values']['pnid_'.$value], 'pseq' => $form_state['values']['pseq_'.$value], 'porig' => $form_state['values']['porig_'.$value], 'ptype' => $form_state['values']['ptype_'.$value], ); break; case 'c_': $links['c'][] = array( 'checked' => $form_state['values']['ccheck_'.$value], 'cnid' => $form_state['values']['cnid_'.$value], 'cseq' => $form_state['values']['cseq_'.$value], 'corig' => $form_state['values']['corig_'.$value], 'ctype' => $form_state['values']['ctype_'.$value], ); break; } } $form_state['values']['links'] = $links; }