'subform', 'title' => t('weblinker'), 'callback' => 'weblinker_form_page', 'type' => MENU_CALLBACK, 'callback arguments' => array( 'edit'=>$_REQUEST, ), 'access' => $access, ); # } if (arg(0) == 'node' && is_numeric(arg(1))) { $node = node_load(arg(1)); if ($node->nid) { $items[] = array( 'path' => 'node/'. arg(1) . '/weblinker', 'title' => t('weblinker'), 'callback' => 'weblinker_page', 'access' => node_access('update', $node), 'type' => MENU_LOCAL_TASK ); } } return $items; } /** * Insert a table listing all embedded links found in this page */ function weblinker_form_alter($form_id, &$form){ if($form_id == 'page_node_form'){ drupal_add_js('misc/progress.js'); drupal_add_js(drupal_get_path('module','weblinker').'/weblinker.js'); // this will cause problems between 4.7 and 5.x /* if(file_exists('misc/jquery.js')){ drupal_add_js('misc/jquery.js'); } else { drupal_add_js(drupal_get_path('module','weblinker').'/jquery.js'); } */ $weblinker_results = weblinker_scan_links($form['#node']); $form['weblinker'] = array( '#value' => theme('weblinker_found_links',$weblinker_results), '#weight' => 5, ); } } /** * Process a page, scanning it for embedded links * * Default is to re-display the page with a button to assist creation of a * corresponding weblink node. * If op is 'auto', the weblinks will be created without any more user input. */ function weblinker_page($op='show_link'){ $node = node_load(arg(1)); drupal_add_js('misc/progress.js'); drupal_add_js(drupal_get_path('module','weblinker').'/weblinker.js'); drupal_set_html_head(''); $weblinker_results = weblinker_scan_links($node); # dsm($weblinker_results); if ($op == 'auto'){ // process the results into new nodes weblinker_create_weblinks($weblinker_results,$node); } // Display the scan results above the page $summary = theme('weblinker_found_links',$weblinker_results); $node->body = $summary . $node->body; return node_show($node, arg(2)); } /** * Find all links in the body of the node. * * Return a prepared array of those links, with weblinks attached if they exist */ function weblinker_scan_links($node){ // find all href links $text = $node->body; $weblinker_results = array(); $found_weblinks = array(); $local_weblinks = array(); // Thanks to Chirp Internet: www.chirp.com.au http://www.the-art-of-web.com/php/parse-links/ // there's a lookbehind assertion (? (from some truly bad input pages) $pattern = "|(]*href=)(['\"]??)([^'\"]+?)\\2([^>]*(?)(.*)|"; if(preg_match_all($pattern."siU", $text, $matches)) {} // $matches[3] is a list of links, // $matches[5] is a list of titles; # dsm($matches); // massage the results into annotatable form foreach($matches[3] as $ix=>$link){ $link = weblinker_scrub_url($link); $url_parts = parse_url($link); $local = (! isset($url_parts['host'])); $weblinks = weblinks_get($link, TRUE); $weblink = array_pop($weblinks); // only use the first found $details = array( 'href' => $link, 'title' => $matches[5][$ix], 'weblink' => $weblink, 'local' => $local, ); $weblinker_results[$link] = $details; if($details['weblink']) { // used for counting $found_weblinks[$link] = $details['weblink']; } if($local){ $local_weblinks[$link] = $details['weblink']; } } if($weblinker_results){ $auto_link = url('node/'. arg(1) . '/weblinker/auto'); drupal_set_message(t('Found %weblinker_count links in the page. %local_count are internal, local references. %found_count are already registered as weblinks. Import all links now - using the current pages properties.',array('%weblinker_count'=>count($weblinker_results), '%found_count' => count($found_weblinks), '%local_count' => count($local_weblinks), '!auto_link'=>$auto_link ))); } return $weblinker_results; } /** * Given an array of links, render them, with some supplimentary info ina * table. * * The array may or may not have been checked at this stage. If checked, they * will have a 'weblink' property attached to them. * */ function theme_weblinker_found_links($weblinker_results){ $rows = array(); foreach($weblinker_results as $details){ $row = array( 'title' => l($details['title'],$details['href']), 'status' => ($details['remote_info']) ? $details['remote_info']['http_code'] : 'unchecked' ); if($details['local']){ $row['status'] = 'local'; } $class = 'status-' . $row['status']; if($details['weblink']){ // It seems valid if($details['weblink']->nid ){ // it exists already $row['status'] = l('linked','node/'.$details['weblink']->nid) ; if($details['remote_info'] && ($details['remote_info']['redirect_count'])){ $row['status'] .= '('. $details['remote_info']['redirect_count'] .' redirects)' ; } $class = 'weblinker-status-linked'; // Add an inline edit action. // // If it already exists, we only have to send the nid, and maybe the parent if($details['weblink']->nid){ $parameter_array = array( 'nid' => $details['weblink']->nid, 'parent_nid' => $details['weblink']->parent_nid, ); } } else { // No weblink exists for this yet // Inline all the data we can $row['status'] = l('create?','node/add/weblinks') ; $parameter_array = $details['weblink']; // send everything we know to the subform } $parameters = http_build_query($parameter_array, NULL, '&'); // drupal l() escapes the ampersand for me, don't do it twice $row['action'] = l('edit', 'subform/weblinks', array('class'=>'sub-form-link'), $parameters ); } // invalid/unchecked link $rows[] = array('data'=>$row, 'class'=>$class); } $attributes = array( 'class' => 'weblinker-summary', ); return theme('table', array_keys($row), $rows, $attributes, 'Links found in this page'); } /** * Given a list of links, instantiate a weblink object for each one. * * Does not double-up if it's already registered * * Pass by reference enables the verification (remote lookup) to set a flag in * the original array. */ function weblinker_create_weblinks(&$link_list, $context_node){ $weblinks_vid = _weblinks_get_vid(); $weblinks_default_tid = weblinks_default_tid(); global $weblinker_count; foreach($link_list as $ix => &$details){ if($details['local']){ continue; } // Check if this is already a known link if(! empty($details['weblink'])){ # foreach($details['weblinks'] as $node){ # drupal_set_message(t("Already have a weblink entry for this, link %link", array('%nid'=>$node->nid, '%link' => $details['href'])) ); # } } else { // Make it on-the-fly now # drupal_set_message(t("Going to create weblink to %link", array('%link' => $details['href'])) ); // use the FAPI rather than do it by hand $form_id = 'weblinks'; $weblink_def = array( 'type' => 'weblinks', 'title' => strip_tags($details['title']), 'body' => $details['title'], 'status' => 1, 'url' => $details['href'], // inheirit parent nodes owner 'name' => $context_node->name, 'uid' => $context_node->uid, // inheirit any classifications the parent node may have had 'taxonomy' => $context_node->taxonomy ? $context_node->taxonomy : array(), ); if(! $weblink_def['taxonomy'][$weblinks_vid]){ // stop weblinks complaining about unclassified links. if($weblinks_default_tid){ $weblink_def['taxonomy'][$weblinks_vid] = array($weblinks_default_tid => $weblinks_default_tid); } else { drupal_set_message(t('Problem initializing new weblink - there is no default term in the weblinks vocab. This can probably be fixed in the weblinks settings'),'error'); } } // Do remote lookups to try and retrieve the links status from the live location. $remote_info = weblinker_fetch_remote_info($details['href']); if($remote_info['http_code'] >= 400){ drupal_set_message(t("Remote lookup for !link failed. Request returned %http_code. This weblink is not going to be created.",array('!link' => l($details['href'],$details['href']), '%http_code' => $remote_info['http_code']) )); } else{ // so far so good. Fill in the retrieved details. // Use the remote pages own description as the local body if($remote_info['description']) { $weblink_def['body'] = '
' . trim(filter_xss($remote_info['description'])) . '
' . $weblink_def['body']; } if($remote_info['title']) { $weblink_def['body'] = '