/[drupal]/contributions/modules/links/links_related.module
ViewVC logotype

Contents of /contributions/modules/links/links_related.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.21 - (show annotations) (download) (as text)
Tue Dec 23 03:07:29 2008 UTC (11 months ago) by syscrusher
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-BETA3, DRUPAL-6--1-0-BETA7, DRUPAL-6--1-0-BETA6, DRUPAL-6--1-0-BETA5, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.20: +13 -1 lines
File MIME type: text/x-php
        Another interim commit. Much of links_admin is
        now functional. The sub-page to list referring
        nodes is not done yet.

        Added documentation for the new hooks in API.html.
        Developers, pay heed!

        Updated links_related and links_weblink to
        implement the new hooks as appropriate.
1 <?php
2 // $Id: links_related.module,v 1.20 2008/12/12 04:10:54 syscrusher Exp $
3
4 // ****************** General hooks ***************************
5
6 function links_related_menu() {
7 $items = array();
8 if (variable_get('links_related_enable_tab',FALSE) && arg(0) == 'node' && is_numeric(arg(1))) {
9 $node = node_load(array('nid' => arg(1)));
10 if ($node->nid) {
11 $items['node/%node/links'] = array(
12 'title' => t('links'),
13 'page callback' => '_links_related_tab',
14 'access callback' => 'node_access',
15 'access arguments' => array('view', $node),
16 'weight' => 9,
17 'type' => MENU_LOCAL_TASK);
18 $items['node/%node/links/list'] = array(
19 'title' => t('list links'),
20 'type' => MENU_DEFAULT_LOCAL_TASK,
21 'weight' => -10);
22 // $items['node/%node/links/edit'] = array(
23 // 'title' => t('edit links'),
24 // 'page callback' => '_links_related_tab_edit',
25 // 'access callback' => 'node_access',
26 // 'access arguments' => array('update', $node),
27 // 'weight' => 10,
28 // 'type' => MENU_LOCAL_TASK);
29 }
30 }
31 $items['admin/settings/links/links_related'] = array(
32 'title' => t('related links'),
33 'description' => t('Configure settings for related links attached to other content.'),
34 'page callback' => 'drupal_get_form',
35 'page arguments' => array('links_related_settings_form'),
36 'access callback' => 'user_access',
37 'access arguments' => array('administer site configuration'),
38 'type' => MENU_LOCAL_TASK,
39 );
40 return $items;
41 }
42
43 function links_related_help($section="") {
44 switch($section) {
45 case 'admin/modules#description':
46 return t("Adds an extra URL field to nodes of admin-specified types.");
47 break;
48 }
49 }
50
51 // **************** Node functions ***********************
52
53 /**
54 * Implementation of hook_link().
55 */
56 function links_related_link($type='', $node=NULL, $teaser=FALSE) {
57 // Only node links supported here
58 if ($type != 'node') {
59 return array();
60 }
61 return _links_related_list($node, FALSE, $teaser, TRUE);
62 }
63
64 /**
65 * Retrieve the list of links to display with the node in the
66 * teaser, page, endnotes, or block.
67 */
68 function _links_related_list(&$node, $page=FALSE, $teaser=FALSE, $statistics=FALSE) {
69 return links_get_list('links_related', $node, $page, $teaser, $statistics);
70 }
71
72 /**
73 * Implementation of hook_settings()
74 */
75 function links_related_settings_form() {
76 $form = array();
77 if (!module_exists('links')) {
78 drupal_set_message(t('The &quot;links&quot; module is disabled or not installed. Node links will not function until this is corrected. Check the availability of that module, and enable if needed, in the !modules.',array('!modules'=>l(t('modules administration page'),'admin/modules'))),'error');
79 }
80
81 $form['link_settings'] = array(
82 '#type' => 'fieldset',
83 '#title' => t('Link display settings'),
84 '#description' => t("Other settings for how the links behave and how they are displayed are available in the !linksettingspage.", array('!linksettingspage'=>l(t('links module settings page'),'admin/settings/links'))),
85 );
86
87 $form['link_settings']['links_related_display_teaser'] = array(
88 '#type' => 'select',
89 '#title' => t('Displayed links (teaser mode)'),
90 '#default_value' => variable_get('links_related_display_teaser','1'),
91 '#options' => array(0=>t('None'), 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, -1=>t('All')),
92 '#description' => t('This setting controls how many links are displayed near the node title (in most themes) for the teaser or listing format.'),
93 );
94
95 $form['link_settings']['links_related_display_full'] = array(
96 '#type' => 'select',
97 '#title' => t('Displayed links (full-page mode)'),
98 '#default_value' => variable_get('links_related_display_full','1'),
99 '#options' => array(0=>t('None'), 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, -1=>t('All')),
100 '#description' => t('This setting controls how many links are displayed near the node title (in most themes) in full-page displays.'),
101 );
102
103 $form['link_settings']['links_related_display_length'] = array(
104 '#type' => 'select',
105 '#title' => t('Display trim length'),
106 '#default_value' => variable_get('links_related_display_length','0'),
107 '#options' => array(0=>t('Unlimited'), 20=>20, 30=>30, 40=>40),
108 '#description' => t('Trims the displayed text (but not the actual URL) for links displayed near the article title. Does not affect display of links as end-notes within the article body.'),
109 );
110
111 $form['link_settings']['links_related_enable_list'] = array(
112 '#type' => 'checkbox',
113 '#title' => t('Show end-notes list'),
114 '#return_value' => 1,
115 '#default_value' => variable_get('links_related_enable_list','1'),
116 '#description' => t('If enabled, list of the article\'s related links will be appended to the end of the content, when in full-page display mode. This listing will also appear as part of the separate links tab (if that feature is enabled).'),
117 );
118
119 $form['link_settings']['links_related_enable_embed_list'] = array(
120 '#type' => 'checkbox',
121 '#title' => t('List embedded links'),
122 '#return_value' => 1,
123 '#default_value' => variable_get('links_related_enable_embed_list','1'),
124 '#description' => t('If enabled, a list of links contained within the article text will be appended to the end of the content, when in full-page display mode. This listing will also appear as part of the separate links tab (if that feature is enabled).'),
125 );
126
127 $form['link_settings']['links_related_enable_tab'] = array(
128 '#type' => 'checkbox',
129 '#title' => t('Show links tab'),
130 '#return_value' => 1,
131 '#default_value' => variable_get('links_related_enable_tab','0'),
132 '#description' => t('If enabled, a tab will be added to node displays to display the list of related and embedded links on their own separate page.'),
133 );
134
135 $form['link_settings']['links_related_always_expand'] = array(
136 '#type' => 'checkbox',
137 '#title' => t('Always expand related links field'),
138 '#return_value' => 1,
139 '#default_value' => variable_get('links_related_always_expand','0'),
140 '#description' => t('This setting causes the related links area in node edit pages to always be expanded by default, although users can still collapse it manually. This can be useful if you want to call attention to the related links area for contributors.'),
141 );
142
143 $form['edit_settings'] = array(
144 '#type' => 'fieldset',
145 '#title' => t('Node edit settings'),
146 '#description' => t("Other settings for how the links behave and how they are displayed are available in the !linksettingspage.", array('!linksettingspage'=>l(t('links module settings page'),'admin/settings/links'))),
147 );
148
149 $form['edit_settings']['links_related_blank_lines'] = array(
150 '#type' => 'select',
151 '#title' => t('Blank link lines'),
152 '#default_value' => variable_get('links_related_blank_lines','2'),
153 '#options' => array(1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8),
154 '#description' => t('This setting controls how many blank &quot;Related Links&quot; lines appear after already-defined links during node editing.'),
155 );
156
157 $form['types'] = array(
158 '#type' => 'markup',
159 '#value' =>'<p>' . t("To choose what content types have link URLs available, use the !contenttypespage to set the 'has related links url' attribute for the desired node types. Note that you may need to revisit this setting if you add modules that define new node types, because the default is OFF for each content type." . "</p>", array('!contenttypespage'=>l(t('content types page'),'admin/content/types'))),
160 );
161
162 return system_settings_form($form);
163 }
164
165 /**
166 * Implementation of hook_nodeapi()
167 */
168 function links_related_nodeapi(&$node, $op, $teaser=NULL, $page=NULL) {
169 //print("nodeapi $op $node->nid<br>\n");
170 switch($op) {
171 // Load the values of the special table from the database as needed
172 case 'load':
173 if (variable_get('links_related_types_'. $node->type, FALSE) && ! is_array($_POST['links_related'])) {
174 $links = links_load_links_for_node($node->nid, 'links_related');
175 return array('links_related'=>$links);
176 }
177 break;
178
179 // Copy values from the POST array into the working copy of the node
180 case 'prepare':
181 if (variable_get('links_related_types_'. $node->type, FALSE) && ! isset($node->links_related)) {
182 _links_related_sort_post_links();
183 $node->links_related = is_array($_POST['links_related']) ? $_POST['links_related'] : array();
184 _links_related_sort_links($node->links_related);
185 }
186 break;
187
188 case 'validate':
189 if (variable_get('links_related_types_'. $node->type, FALSE) && isset($node->links_related)) {
190 _links_related_sort_post_links();
191 _links_related_sort_links($node->links_related);
192 foreach($node->links_related as $i=>$link) {
193 $node->links_related[$i]['url'] = links_normalize_url($link['url']);
194 }
195 }
196 break;
197
198 // Delete the values from a node that is being erased
199 // Don't care if it's "supposed" to have links -- delete if found anyway
200 case 'delete':
201 links_delete_links_for_node($node, 'links_related');
202 break;
203
204 // Update the values in an existing record, or insert a new record.
205 case 'insert':
206 case 'update':
207 if (variable_get('links_related_types_'. $node->type, FALSE)) {
208 links_save_links_for_node($node, 'links_related');
209 }
210 break;
211 case 'view':
212 $links =& links_load_links_for_node($node->nid, 'links_related');
213 $GLOBALS['links_related'] = array(
214 'node'=>$node, 'links'=>$links
215 );
216 $node->content['links_related'] = array(
217 '#value' => _links_related_prep_view($node, $teaser, $page),
218 '#weight' => 1,
219 );
220 break;
221 }
222 }
223
224 function links_related_form_alter(&$form, $form_state, $form_id) {
225 $node = $form['#node'];
226 switch ($form_id) {
227 case 'node_type_form':
228 // Nodetype-specific settings
229 $type = $form['old_type']['#value'];
230 $form['links_related'] = array(
231 '#type' => 'fieldset',
232 '#title' => t("Related links"),
233 '#collapsible' => TRUE,
234 '#collapsed' => TRUE,
235 '#tree' => FALSE,
236 );
237 $form['links_related']['links_related_types'] = array(
238 '#type' => 'radios',
239 '#title' => t('Allow related links'),
240 '#options' => array(0=>t('Disabled'), 1=>t('Optional'), 2=>t('Required')),
241 '#default_value' => variable_get('links_related_types_'. $type, 0),
242 '#description' => t('This setting enables or disables related links for this content type.'),
243 );
244 // Make sure the buttons are last
245 $form['submit']['#weight'] = 15;
246 $form['reset']['#weight'] = 16;
247 $form['delete']['#weight'] = 17;
248 break;
249
250 case $node->type .'_node_form':
251 // The actual node edit form. This allows the users to enter the
252 // links_related into appropriate node types' edit screens.
253 if (variable_get('links_related_types_'.$node->type, 0)) {
254 _links_related_sort_links($node->links_related);
255 $links =& $node->links_related;
256
257 $form['links_related'] = array(
258 '#type' => 'fieldset',
259 '#tree' => TRUE,
260 '#title' => t('Related Links'),
261 '#description' => t('Links are stored as part of the !page. Monitoring and dead link detection are centrally managed from there. <strong>To add more links, just click &quot;Preview&quot; to add another blank row. To remove a link from this article, just blank out its URL field or check the Delete box.</strong> If you blank out the title but leave the URL, then the system will suggest a title for you. The Weight allows you to determine the order in which links are displayed; lower numbers float to the top.',array('!page'=>l(t('links management feature'),'admin/content/links'))),
262 // Not collapsible if links are required
263 '#collapsible' => variable_get('links_related_types_'.$node->type, 0) < 2,
264 '#collapsed' => (count($links) == 0 && ! variable_get('links_related_always_expand',0)),
265 //'#weight' => -16,
266 );
267
268 $form['links_related']['#theme'] = 'links_related_form';
269 // Existing links first
270 $i = 0;
271 foreach ($links as $link) {
272 $form['links_related'][$i++] = links_related_form_line($link);
273 }
274 $blanks = variable_get('links_related_blank_lines','2');
275 for ($j=0; $j<$blanks; $j++) {
276 $form['links_related'][$i++] = links_related_form_line(NULL);
277 }
278 if (variable_get('links_related_types_'.$node->type, 0) >= 2) {
279 // The first one is required
280 $form['links_related'][0]['url']['#required'] = 1;
281 $form['links_related']['#title'] .= ' '.t('(at least one link required for this content type)');
282 }
283 }
284 break;
285 }
286 }
287
288 /**
289 * Implements hook_theme to register our theme functions
290 */
291 function links_related_theme($existing, $type, $theme, $path) {
292 return array(
293 'links_related_form' => array(
294 'arguments' => array('element' => NULL),
295 ),
296 );
297 }
298
299 /**
300 * This function wraps the related links form fields in a table for display.
301 */
302 function theme_links_related_form($form) {
303 $header = array(t('URL'), t('Title'), t('Weight'), t('Delete'));
304
305 $rows = array();
306 $i = 0;
307 foreach (element_children($form) as $key) {
308 $rows[$i] = array();
309 $rows[$i][0] = drupal_render($form[$key]['url']);
310 $rows[$i][1] = drupal_render($form[$key]['link_title']);
311 $rows[$i][2] = drupal_render($form[$key]['weight']);
312 $rows[$i][3] = drupal_render($form[$key]['delete']);
313 $i++;
314 }
315 $output = theme('table', $header, $rows);
316 $output .= drupal_render($form);
317 return $output;
318 }
319
320 /**
321 * Implementation of hook_block()
322 */
323 function links_related_block($op = 'list', $delta = 0, $edit = array()) {
324 switch($op) {
325 case 'list':
326 $blocks = array(0=>array('info'=>t('Related links')));
327 return $blocks;
328 case 'view':
329 $block = array();
330 switch($delta) {
331 case 0:
332 $block['subject'] = t('Related Links');
333 if (arg(0) == 'node' && is_numeric(arg(1)) && is_array($GLOBALS['links_related']['links']) && is_object($GLOBALS['links_related']['node'])) {
334 // $links =& $GLOBALS['links_related']['links'];
335 $node =& $GLOBALS['links_related']['node'];
336 $list =& _links_related_list($node, TRUE, FALSE, FALSE);
337 if (count($list)) {
338 $block['content'] = _links_related_format_list($list);
339 }
340 }
341 }
342 return $block;
343 }
344 }
345
346 /********************************************************************
347 * Internal functions
348 ********************************************************************/
349
350 /**
351 * Builds one one line of the data entry form for links
352 */
353 function links_related_form_line($link=NULL) {
354 $link = (array)$link;
355
356 $entry['url'] = array(
357 '#type' => 'textfield',
358 '#default_value' => $link['url'],
359 );
360
361 $entry['link_title'] = array(
362 '#type' => 'textfield',
363 '#default_value' => $link['link_title'],
364 );
365
366 $entry['weight'] = array(
367 '#type' => 'weight',
368 '#default_value' => (empty($link['weight']) ? 0 : $link['weight']),
369 '#delta' => 5,
370 );
371
372 $entry['delete'] = array(
373 '#type' => 'checkbox',
374 '#return_value' => 1,
375 '#default_value' => $link['delete'],
376 );
377
378 return $entry;
379 }
380
381 /**
382 * Compares two subarrays from $node->links_related and returns
383 * an integer -1, 0, or 1 based on that comparison. (See PHP
384 * function uasort() for details.)
385 */
386 function _links_related_linkcompare($link1, $link2) {
387 if (intval($link1['weight']) == intval($link2['weight'])) {
388 if ($link1['link_title'] == $link2['link_title']) {
389 return 0;
390 } else {
391 return ($link1['link_title'] < $link2['link_title']) ? -1 : 1;
392 }
393 } else {
394 //print("Sort by weight ".intval($link1['weight'])." vs ".intval($link2['weight'])."<br>\n");
395 return (intval($link1['weight']) < intval($link2['weight'])) ? -1 : 1;
396 }
397 }
398
399 /**
400 * Sorts the links by weight, keeping their existing order otherwise.
401 * Also removes any empty links and those with the "delete" flag set.
402 * $links is an integer-subscripted array of links.
403 */
404 function _links_related_sort_links(&$links) {
405 if (is_array($links)) {
406 foreach ($links as $i=>$link) {
407 if ($link['delete'] || empty($link['url'])) {
408 unset($links[$i]);
409 }
410 }
411 uasort($links, '_links_related_linkcompare');
412 }
413 }
414
415 /**
416 * Works like _links_related_sort_links(), except operates
417 * on $_POST['links_related'] intrinsically, rather
418 * than accepting a node as a parameter.
419 */
420 function _links_related_sort_post_links() {
421 if (is_array($_POST['links_related'])) {
422 // Delete any empty ones and renumber the rest to prevent
423 // problems during rendering of blank lines
424 $new = array();
425 foreach ($_POST['links_related'] as $i=>$link) {
426 if (!$link['delete'] && (!empty($link['url']) || !empty($link['link_title']))) {
427 $new[] = $_POST['links_related'][$i];
428 }
429 }
430 $_POST['links_related'] = $new;
431 uasort($_POST['links_related'], '_links_related_linkcompare');
432 }
433 }
434
435 /**
436 * Prepares a view of the links depending on the node viewing mode
437 * and the links_related module settings.
438 */
439 function _links_related_prep_view(&$node, $teaser=FALSE, $page=FALSE) {
440 if ($teaser) {
441 return '';
442 }
443 $do_related = variable_get('links_related_enable_list',TRUE);
444 $do_embed = variable_get('links_related_enable_embed_list',TRUE);
445 if ($do_related || $do_embed) {
446 $links =& links_load_links_for_node($node->nid, 'links_related');
447 if (! count($links)) {
448 return '';
449 }
450 $html = '';
451 if ($do_related) {
452 $list = _links_related_list($node, TRUE, FALSE, TRUE);
453 $html .= _links_related_format_list($list, t('Related Links'));
454 }
455 if ($do_embed) {
456 $html .= _links_related_embedded($node, FALSE);
457 }
458 }
459 return $html;
460 }
461
462 /**
463 * Accepts a list of predefined HTML links (as returned from links_get_list())
464 * and returns the list HTML around them plus an optional level-2 heading
465 * at the top of the list. The entire thing is surrounded by a DIV tag
466 * with a class of "links_related_endnotes" to make it more themeable.
467 */
468 function _links_related_format_list($list, $heading='') {
469 // Trivial rejection
470 if (count($list) < 1) {
471 return '';
472 }
473 $html = '<div id="links_related_endnotes">';
474 if (! empty($heading)) {
475 $html .= '<h2>' . $heading . '</h2>';
476 }
477 $html .= '<ul class="links_link_list">';
478 foreach ($list as $link) {
479 $html .= '<li>' . l($link['title'], $link['href'], $link['attributes']);
480 }
481 $html .= '</ul>';
482 $html .= '</div>';
483 return $html;
484 }
485
486 /**
487 * Displays the standalone "links" tab for a node
488 */
489 function _links_related_tab() {
490 $html = '';
491 if (arg(0) == 'node' && is_numeric(arg(1))) {
492 $node = node_load(array('nid' => arg(1)));
493 if ($node->nid) {
494 drupal_set_title($node->title);
495 $html .= _links_related_prep_view($node, FALSE, FALSE);
496 } else {
497 drupal_not_found();
498 }
499 }
500 print(theme('page',$html));
501 }
502
503 /**
504 * Displays a page to allow management of the embedded links.
505 */
506 function _links_related_tab_edit() {
507 $html = _links_related_embedded(NULL, TRUE);
508 print(theme('page',$html));
509 }
510
511 /**
512 * Provides either a displayable (read-only) listing, in endnotes
513 * format, or an editable form, showing all of the embedded links
514 * in the node body.
515 */
516 function _links_related_embedded($node=NULL, $editable=FALSE) {
517 if (! is_object($node)) {
518 // Try to find the node ID from the Drupal path
519 if (arg(0) == 'node' && is_numeric(arg(1))) {
520 $nid = intval(arg(1));
521 $node2 = node_load(array('nid'=>$nid));
522 } else {
523 // Dereference to be sure we don't touch original.
524 $node2 = $node;
525 }
526 if (! $node2->nid) {
527 return array();
528 }
529 } else {
530 // Some node types -- notably book pages -- dink around with the
531 // body and add extraneous links that we don't want. So we have
532 // to go back to the database for the original body.
533 if ($node->type == 'book') {
534 $node2 = node_load(array('nid'=>$node->nid));
535 } else {
536 $node2 = $node;
537 }
538 }
539 $text = $node2->body;
540 // TODO -- add an API hook that allows modules to expose other text to this
541 // link-hunting process
542 $links =& links_find_links($text);
543 if ($editable) {
544 return drupal_get_form('links_related_embedded_form', $links, $node2);
545 } else {
546 return _links_related_format_embedded_list($links);
547 }
548 }
549
550 /**
551 * This function simply displays the embedded links in endnotes-style, without
552 * providing a form for editing.
553 */
554 function _links_related_format_embedded_list($links) {
555 $list = array();
556 foreach ($links as $i=>$link) {
557 $url = $link['url']; // Get the normalized URL
558 $display_url = htmlspecialchars(strlen($url) > 60 ? substr($url, 0, 57) . '...' : $url);
559 $display_text = (empty($link['title']) || $link['title'] == $url) ? $display_url : $link['title'];
560 $attribs = array('title'=>t('Matched text: !match', array('!match'=>$link['matched'])));
561 $list[] = array('title'=>$display_text, 'href'=>$url, 'attributes'=>$attribs);
562 }
563 return _links_related_format_list($list, t('Links from Article Text'));
564 }
565
566 /**
567 * Given an array of links as returned from links_find_links(),
568 * this function returns an editable form to manage those links.
569 *
570 * @param array $links link definitions (as extracted from the text)
571 * @param node $node Context node
572 */
573 function links_related_embedded_form($links, $node) {
574 $form = array(
575 'links_embed' => array(
576 '#type' => 'fieldset',
577 '#title' => t('Embedded Links'),
578 '#collapsible' => 1,
579 '#tree' => 1,
580 '#description' => t('These are the links found inside the page content. You can choose to replace the direct URLs with managed links from the site\'s links catalog (adding new links if necessary), or to replace existing catalog links with the actual direct URLs. Titles added or changed here do not override titles for the same link if it appears on other pages.'),
581 ),
582 'nid' => array(
583 '#type' => 'hidden',
584 '#default_value' => $node->nid,
585 )
586 );
587 $goto = url('links/goto') . '/';
588 $linked_links = links_load_links_for_node($node->nid, '', 0, FALSE, 'url');
589 foreach ($links as $i=>$link) {
590
591 $url = links_normalize_url($link['url']); // Get the normalized URL
592 # Set $reverse TRUE if the URL is already one of our "goto" URLs
593 if (preg_match('!^(?:/*)'.$goto.'!', $url)) {
594 $reverse = TRUE;
595 } else {
596 $reverse = FALSE;
597 }
598 $exists = FALSE; // already in the catalog
599 $attached = FALSE; // already associated with this node
600 $weblink_exists = FALSE; // whether a stand-alone weblinks node page exists for this already
601
602 $display_url = theme('display_url',$url);
603 $attributes = array('title'=>t('Matched text: !match', array('!match'=>$link['matched'])));
604
605 $existing_link = links_get_link($url);
606 if(is_array($existing_link) && $existing_link['url']){
607 $exists = TRUE;
608 $attributes['class'] = 'existing';
609 # dsm("Found an entry for ".$existing_link['url']." already");
610
611 // already attached to this node, cool
612 if($linked_links[$url]){
613 $existing_link = $linked_links[$url];
614 $attributes['class'] .= ' attached';
615 $attached = TRUE;
616 }
617
618 // lookup to see if it has a weblinks node attached
619 $referers = links_get_link_node_refs($existing_link['lid']);
620 foreach($referers as $ref){
621 if($ref['module'] == 'links_weblink'){
622 $weblink_exists = $ref['nid'];
623 }
624 }
625
626 } else {
627 # dsm("$url does not yet have an entry");
628 unset($existing_link); // an empty placeholder gets in the way @TODO ensure the suggested patch to the API goes through
629 }
630
631 $form_row = array(
632 '#attributes' => $attributes,
633 );
634
635 if($existing_link && ($existing_link['link_title'] != $link['title'])){
636 $aka = t('also known as: %aka', array('%aka' => $existing_link['link_title']));
637 }
638 else {$aka = '';}
639
640 $form_row['title'] = array(
641 '#type' => 'textfield',
642 '#title' => t('Found title'),
643 '#size' => 40,
644 '#default_value' => $link['title'],
645 '#description' => $aka,
646 );
647 $form_row['url'] = array(
648 '#type' => 'textfield',
649 '#title' => t('URL') ." <small>". l($display_url, $url) ."</small> " ,
650 '#size' => 40,
651 '#maxlength' => 500, // required to handle insane redirect URLs. Drupal sets it to 128, so cannot leave it open
652 '#default_value' => $url,
653 );
654 $form_row['op'] = array(
655 '#tree' => TRUE
656 );
657
658 if(! $exists) {
659 $form_row['op']['link_item'] = array(
660 '#type' => 'checkbox',
661 '#title' => $reverse ? t('Make non-catalog link') : t('Make catalog link'),
662 '#default_value' => '0',
663 '#return_value' => $reverse ? 'delete' : 'create',
664 );
665 }
666 else {
667 if(module_exists('links_admin')){
668 $form_row['op']['link_item'] = array(
669 '#value' => l(t('Administer link'),'admin/content/links/'.$existing_link['lid'] )
670 );
671 }
672 }
673
674 $form_row['op']['attach_to_node'] = array(
675 '#type' => 'checkbox',
676 '#title' => $attached ? t('Detach from this node') : t('Attach to this node'),
677 '#default_value' => '0',
678 '#return_value' => $attached ? 'detach' : 'attach',
679 );
680
681 // Add the option to make a weblink page on the fly
682 if(module_exists('links_weblink')){
683 if($weblink_exists){
684 $form_row['op']['weblink'] = array(
685 '#value' => l(t('Weblink page'),'node/'.$weblink_exists) . ' [' . l(t('Edit'),'node/'.$weblink_exists.'/edit') .']',
686 );
687 }
688 else {
689 $form_row['op']['weblink'] = array(
690 '#type' => 'checkbox',
691 '#title' => t("Create weblink page"),
692 '#default_value' => '0',
693 '#return_value' => 'create',
694 );
695 }
696 }
697
698 // if we have an existing link id, remember it. It may come in handy, especially for ajax later on
699 if($existing_link['lid']){
700 $form_row['lid'] = array(
701 '#type' => 'hidden',
702 '#default_value' => $existing_link['lid'],
703 );
704 }
705
706 $form['links_embed'][$i] = $form_row;
707 }
708 $form['submit'] = array(
709 '#type' => 'submit',
710 '#value' => t('Save changes'),
711 );
712 return $form;
713 }
714
715 function links_related_embedded_form_submit($form_id,$form_values) {
716 $node = node_load($form_values['nid']);
717 foreach($form_values['links_embed'] as $link_entry){
718 foreach($link_entry['op'] as $op => $action){
719 // The op handling is nested so we can do multiple
720 // maintainence actions independantly
721 if($action){
722 # dsm("need to modify $op to $action on ".$link_entry['url']);
723 switch($op){
724 case 'link_item' :
725 if($action == 'create'){
726 // make it but don't link it
727 $link_entry['lid'] = links_put_link($link_entry['url'], $link_entry['title'] );
728 }
729 break;
730 case 'attach_to_node' :
731 if($action == 'attach'){
732 // the API recommend this action be done in bulk. See later
733 $link_entry['link_title'] = $link_entry['title'];
734 $node->links_related[$link_entry['url']] = $link_entry;
735 }
736 if($action == 'detach'){
737 unset($node->links_related[$link_entry['url']]);
738 }
739 break;
740 case 'weblink' :
741 if($action == 'create'){
742 global $user;
743 $new_node = (object)array(
744 'title' => $link_entry['title'],
745 'body' => $link_entry['title'],
746 'type' => 'weblink',
747 'uid' => $user->uid,
748 'status' => 1,
749 'links_weblink_url' => $link_entry['url'],
750 );
751 node_save($new_node);
752 drupal_set_message(t('Created a standalone weblink page for the link !page_link. !edit_link',
753 array(
754 '!page_link' => l($new_node->title,'node/'.$new_node->nid),
755 '!edit_link' => l(t('Edit'), 'node/'.$new_node->nid.'/edit')
756 )
757 ));
758 }
759 break;
760 }
761 }
762 }
763 }
764 // @see links_save_links_for_node();
765 links_save_links_for_node($node, 'links_related');
766 }
767
768 /**
769 * This function wraps the embedded links form fields in a table for display.
770 */
771 function theme_links_related_embedded_form(&$form) {
772 $header = array(t('Link Title').'<br />'.t('and URL'), t('Operations'));
773 $rows = array();
774 foreach (element_children($form['links_embed']) as $key) {
775 $row = $form['links_embed'][$key]['#attributes'] ? $form['links_embed'][$key]['#attributes'] : array();
776 $row['data'][] = drupal_render($form['links_embed'][$key]['title']) . '<br />' . drupal_render($form['links_embed'][$key]['url']);
777 #$row['data'][] = $form['links_embed'][$key]['#attributes']['class'];
778 $row['data'][] = drupal_render($form['links_embed'][$key]['op']);
779 $rows[] = $row;
780 }
781 // pre-render this set into a table before letting Drupal do the rest of the form
782 $form['links_embed']['#children'] = theme('table', $header, $rows);
783 $output .= drupal_render($form);
784 return $output;
785 }
786
787 /**
788 * Return an array of all places the given link is associated with - a reverse
789 * lookup on the links_node table.
790 *
791 * Used to find if this link is mentioned elsewhere already
792 *
793 * @TODO move this into the API if appropriate
794 *
795 */
796 function links_get_link_node_refs($lid) {
797 $sql = "SELECT * FROM {links_node} WHERE lid = %d";
798 $result = db_query($sql,$lid);
799 $referrers = array();
800 while($link_ref = db_fetch_array($result)){
801 $referrers[$link_ref['nid']] = $link_ref;
802 }
803 return $referrers;
804 }
805
806 /**
807 * Implements hook_links_delete_link_reference to remove $lid from
808 * the {links_node} table for records used by this module.
809 */
810 function links_related_links_delete_link_reference($lid) {
811 db_query("DELETE FROM {links_node} WHERE lid=%d AND module='links_related'", $lid);
812 if (db_error()) {
813 watchdog("links","links delete references for link !lid failed for links_related module", array('!lid'=>$lid), WATCHDOG_ERROR);
814 } else {
815 watchdog("links","Deleted references for link !lid for links_related module", array('!lid'=>$lid), WATCHDOG_INFO);
816 }
817 }

  ViewVC Help
Powered by ViewVC 1.1.2