yellow.module

// $Id:$ //

/* Yellow, a prototype */

/*

--
 -- Table structure for table `yellow_node`
--
 
 CREATE TABLE yellow_node (
  bid varchar(40) NOT NULL default '0',
  nid int(11) NOT NULL default '0',
  UNIQUE KEY bid (bid),
  KEY nid (nid)
);

*/


/**
 * Implementation of hook_help
 */

function yellow_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('A Yellow Advantage prototype.');
      break
    }
}

/**
 * Implementation of hook_perm
 */

function yellow_perm() {
  return array('administer yellow', 'view yellow');
}

/**
 * Implementation of hook_menu
 */

function yellow_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array('path' => 'admin/settings/yellow',
       'title' => t('Yellow'),
      'access' => user_access('administer yellow'),
      'callback' => 'yellow_configure'); 
      $items[] = array('path' => 'yellow',
       'title' => t('Yellow'),
      'access' => user_access('view yellow'),
      'callback' => 'yellow_page');     
          $items[] = array('path' => 'admin/settings/yellow/configure',
       'title' => t('Yellow'),
      'access' => user_access('administer yellow'),
      'type' => MENU_DEFAULT_LOCAL_TASK,
      'weight' => -10,
      'callback' => 'yellow_configure');       
            $items[] = array('path' => 'admin/settings/yellow/cache',
       'title' => t('Clear the yellow cache'),
      'access' => user_access('administer yellow'),
      'type' => MENU_LOCAL_TASK,
      'callback' => 'yellow_cache');       
          }
  else {
    $items[] = array('path' => 'yellow/listing/' . arg(2),
       'title' => t('Yellow'),
      'type' => MENU_CALLBACK,
      'access' => user_access('view yellow'),
      'callback' => 'yellow_listing');
    $items[] = array('path' => 'yellow/category/' . arg(2),
       'title' => t('Yellow'),
      'type' => MENU_CALLBACK,
      'access' => user_access('view yellow'),
      'callback' => 'yellow_category');   
      }
  return $items;
}

/**
 * Clear the yellow cache (during testing)
 */

function yellow_cache() {
  cache_clear_all('yellow', TRUE);
  drupal_set_message(t('<p>Cache cleared.</p>'));
  drupal_goto(referer_uri());
}


/**
 * Admin screen
 */

function yellow_configure() {
  $form = array();
  return 'hi';
}

/**
 * Generic page function
 */

function yellow_page() {
  $keys = urlencode(arg(1));
  $appid = 'REMOVED FOR DEMO';
  if (empty($keys)) $keys = 'pizza';
  $base = 'http://local.yahooapis.com/LocalSearchService/V2/localSearch?appid='. $appid .'&output=php&results=20&zip=30907&query=' . $keys;
  $data = yellow_fetch($base);
  $data = unserialize($data);
  return print_k($data, TRUE);
}

/**
 * Implementation of hook_search
 */

function yellow_search($op = 'search', $keys = null) {
  switch ($op) {
    case 'name':
       return t('Y! Local');
    case 'search':
      $result_arrays = _yellow_types();
      $pagesize = variable_get('yellow_per_page' , 20);
      $pagestart = $_GET['page'];
      $start = $pagestart * $pagesize + 1;
      $sort = '';
      $keys = urlencode($keys);
      $data = cache_get('yellow:' . $keys . ':' . $pagestart);
      $yahoo = unserialize($data->data);
      if (empty($yahoo)) {
        $base = "http://local.yahooapis.com/LocalSearchService/V2/localSearch?appid=IjITNsDV34Ec5CYvqBDTXKlXkZyVnnCQrqLQG_DI0AbPV.n5RTm1tZCtiWjSR1PReg--&output=php&results=20&zip=30907&query=$keys&start=$start";
        $yahoo = yellow_fetch($base);
        print 'fresh';
        cache_set('yellow:' . $keys . ':' . $pagestart, 'cache', serialize($yahoo));
      } 
        $results = unserialize($yahoo);
      $data = $results['ResultSet'];
      $find = array();
      $find['count'] = $data['totalResultsAvailable'];
      $find['start'] = ($pagestart) * $pagesize + 1;
      $find['stop'] = (($pagestart +1) * $pagesize);         
                $i =0;
      foreach ($data['Result'] as $listing) {
        // derive the id
        $url = $listing['ClickUrl'];
        $link = parse_url($url, PHP_URL_QUERY);
        $q = explode('&', $link);
        $s = explode('=', $q[0]);
        $id = $s[1];
        // stick the results in cache for each listing
        cache_set('yellow:' . 'listing' . ':' . $id, 'cache', serialize($listing));  
           $find[$i]['title'] = $listing['Title'];
        $find[$i]['link'] =  'yellow/listing/' . check_plain($id);
        $sql = "SELECT nid FROM {yellow_node} WHERE bid = %d";
        $check = db_fetch_object(db_query($sql, $id));
        if ($check->nid > 0) {
          $find[$i]['link'] =  "node/$check->nid";
        }
        $find[$i]['snippet'] = check_plain($listing['Distance']) . ' miles' . '<br />' . check_plain($listing['Address']) . ' ' . check_plain($listing['City']) . ', ' . check_plain($listing['State']) . ' | ' . check_plain($listing['Phone']) . '<br />';
        $i++;
      }
      return $find;
    default:
      return;
  }
}

/**
 * Implementation of hook_search_item
 */

function yellow_search_item($item) {
  $output = '<li>';
  $output .= l($item['title'], $item['link']) . '<br />';
  $output .= $item['snippet'];
  $output .= '</li><br />';
  return $output;  
   }

/**
 * Implemetation of hook_search_page
 */

function yellow_search_page($results, $type = 'yellow') {
  $count = array_shift($results);
  $start = array_shift($results);
  $stop = array_shift($results);
  if ($stop > $count) {
    $stop = $count;
  }
  $data = $results;
  foreach ($data as $item) {
    $listings .= yellow_search_item($item);
  }
  $output = t('<p>Showing matches %start to %stop of %count.</p>', array('%start' => $start, '%stop' => $stop, '%count' => $count));
  $output .= '<ol start="' . $start . '">';
  $output .= $listings;
  $output .= '</ol>';
  $output .= yellow_get_pager($count, $element);
  return $output;
}

/**
 * Theme a pager for the search results
 */

function yellow_get_pager($count = 0, $element = 0) {
   $output = '';
  if ($count > 0) {
    global $pager_page_array, $pager_total, $pager_total_items;
     $page = isset($_GET['page']) ? $_GET['page'] : '';
    $pager_page_array = explode(',', $page); 
      $pager_total_items[0] = $count;
    $limit = variable_get('yellow_per_page' , 20);
    $pager_total[0] = ceil($count / $limit); 
      $output .= theme('pager', array(), $limit, 0, array());
  }
  return $output;
}
 /**
 * View listings by category
 */

function yellow_category($cid = 0) {
  $cid = arg(2);
  // error capture 
  
  if ($cid == 0) {
    drupal_set_message(t('Invalid category specified.'), 'error');
    return '';
  }
  // success routine 
  
  else {
    return 'yellow' . $bid;
  } 
  }

/**
 * View a business listing
 */

function yellow_listing($bid = 0) {
  $bid = arg(2);
  // error capture
  if (empty($bid)) {
    drupal_set_message(t('Invalid id specified.'), 'error');
    return '';
  }
  // success routine
  else {
    $data = cache_get('yellow:' . 'listing' . ':' . $bid);
    $xml = unserialize($data->data);
    // create a new node?
    $check = _yellow_check_id($bid);
    if ($check == 0) {
      $input = _yellow_parse_listing($xml);
      $node = yellow_create_node($bid, $input['title'], $input['tags'], $input['location'], $input['body']); 
        drupal_goto("node/$node");
      return;
    }   
        else {
      $output = 'yellow' . $bid;
      $output .= print_k($xml);
      return $output;
    } 
    } 
  }

/**** Node creation and editing functions ****/

/**
 * Implementation of hook_node_info()
 */

function yellow_node_info() {
  return array('yellow' => array('name' => t('yellow'), 'module' => 'yellow', 'base' => 'yellow'));
}

/**
 * Implementation of hook_load()
  */

function yellow_load($node) {
  $sql = 'SELECT bid FROM {yellow_node} WHERE nid = %d';
  $result = db_fetch_object(db_query($sql, $node->nid));
  $bid = $result->bid;
  $data = cache_get('yellow:listing:' . $bid);
  $xml = unserialize($data->data);
   // get the right data array based on type
  $extra = new stdClass;
  $extra->bid = $bid;
  $extra->xml = $xml;
  return $extra;
}

/**
  * Implementation of hook_view()
 */

function yellow_view(&$node, $teaser = FALSE, $page = FALSE) {
  $node = node_prepare($node, $teaser);
  $node->content['myfield'] = array(
    '#value' => theme('yellow_node', $node, $teaser),
    '#weight' => 1,
  );  
     $map = yellow_gmap($node->xml);
  print $map;
  return $node;
}

/**
 * Uses the GMap API
 */

function yellow_gmap($xml) {
    $output = '//<![CDATA[

    function load() {
      if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById("map"));
        var point = new GLatLng('
. $xml['Latitude'] . ', ' . $xml['Longitude'] . ');
        map.addControl(new GSmallMapControl());
        map.addControl(new GMapTypeControl());
        map.setCenter(point, 13);
        var bounds = map.getBounds();
        var southWest = bounds.getSouthWest();
        var northEast = bounds.getNorthEast();
        var lngSpan = northEast.lng() - southWest.lng();
        var latSpan = northEast.lat() - southWest.lat();
        map.addOverlay(new GMarker(point));
      }
    }
    //]]>'
;
    drupal_add_js($output, 'inline');
    return;
}

 
 
 /**
 * Theme for node
 */

function theme_yellow_node($node, $teaser = FALSE) {
  $xml = $node->xml;
  $address = $xml['Address'] . ' ' . $xml['City'] . ', ' . $xml['State'];
  $output = "<p>$address</p>";
  $output .= "<p>". $xml['Phone'] . "</p>";
  $output .= "<p>" . l($xml['BusinessUrl'], $xml['BusinessClickUrl'], array(), NULL, NULL, TRUE) . "</p>";
  if (!$teaser) {
    $output .= '<div id="map" style="width: 500px; height: 300px"></div>';
  } 
    return $output;
}


/**
 * Implementation of hook_insert()
  */

function yellow_insert($node) {
  $sql = "INSERT INTO {yellow_node} (bid, nid) VALUES (%d, %d)";
  db_query($sql, $node->bid, $node->nid);
}

/**
 * Implementation of hook_delete()
 */

function yellow_delete($node) {
  $sql = "DELETE FROM {yellow_node} WHERE nid=%d";
  db_query($sql, $node->nid); 
  }

/**
 * Create a yellow node on page view
 */

function yellow_create_node($bid, $title, $tags = array(), $location = array(), $body = 'placeholder') {
  if (!empty($bid) && !empty($title)) {
    $node = array();
    // define the default node
    $node['title'] = $title;
    $node['body'] = '';
    $node['teaser'] = '';
    $node['created'] = time();
    $node['comment'] = 2;
    $node['type'] = 'yellow';
    if (variable_get('yellow_tags', 1) == 1 && !empty($tags)) {     
            if (count($tags) > 1) {
        $tags = implode(', ', $tags);
      }
      $vid = variable_get('yellow_vocabulary', 1);
      $node['taxonomy']['tags'][$vid] = $tags;     
          } 
      if (variable_get('yellow_tag_location', 1) == 1 && !empty($location)) {     
            $vid = variable_get('yellow_location_vocabulary', 1);
      $node['taxonomy']['tags'][$vid] = $location;     
          } 
      $node['bid'] = $bid;

    node_submit(&$node);
    node_save(&$node);
    return $node->nid;
  } 
  }



/**** Search box functions ****/

/**
 * Implementation of hook_block().
 */

function yellow_block($op = 'list', $delta = 0) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Yellow search form');
    return $blocks;
  }
  else if ($op == 'view' && user_access('search content')) {
    $block['content'] = yellow_search_box('yellow_search_block_form');
    $block['subject'] = t('Y! Local');
    return $block;
  }
}

/**
 * Output a search form for the search block and the theme's search box.
 */

function yellow_search_box($form_id = 'yellow_search_theme_form') {
  return drupal_get_form('yellow_search_box_form', $form_id);
}

function yellow_search_box_form($form_id) {
  // Use search_keys instead of keys to avoid ID conflicts with the search block.
  $form['y_keys'] = array(
    '#type' => 'textfield',
    '#size' => 15,
    '#default_value' => '',
    '#title' => t('Search for'),
  );
  $form['#action'] = url('search/yellow/');
  $form['submit'] = array('#type' => 'submit', '#value' => t('Search'));
  return $form;

  
  /**
 * Process a block search form submission.
 */

function yellow_search_box_form_submit($form_id, $form_values) {
  return 'search/yellow/'urlencode(trim($form_values['y_keys']));
}

/**
 * Theme the theme search form.
 */

function theme_yellow_search_theme_form($form) {
  return '<div id="search" class="container-inline">'. form_render($form) .'</div>';
}

/**
 * Theme the block search form.
 */

function theme_yellow_search_block_form($form) {
  return '<div class="container-inline">'. form_render($form) .'</div>';
}

/**** Helper functions ****/

function _yellow_parse_listing($xml) {
  $data['title'] = $xml['Title'];
  $data['tags'] = array();
  $data['location'] = array();
  $data['body'] = check_plain($xml['Distance']) . ' miles' . '<br />' . check_plain($xml['Address']) . ' ' . check_plain($xml['City']) . ', ' . check_plain($xml['State']) . ' | ' . check_plain($xml['Phone']) . '<br />';
  // prep locative info to save as tags
  $location = $xml['City'];
  $location .= ', ' . $xml['State'];     
        $data['location'] = $location;
  return $data;
}

function _yellow_types() {
  $types = array('featuredResults', 'ldacResults', 'localResults', 'nationalResults', 'courtesyResults');
  return $types;
}

function _yellow_check_id($bid) {
  $sql = "SELECT nid FROM {yellow_node} WHERE bid = '%s'";
  $node = db_fetch_object(db_query($sql, $bid));
  return $node->nid;
}

/**
 * Fetch data from yahoo!
 */

function yellow_fetch($url) {
  $result = drupal_http_request($url);
  if ($result->code == 200) {
    return $result->data;
  }
  else {
    return t('Failed to get REST document');
  }
}
/**** XML functions ****/

/**
 * simple xml
 */

function yellow_simple_xml($url) {
  // Get XML from the specified URL
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $xml_data = curl_exec($ch);
  curl_close($ch);
  if (empty($xml_data)) {
    drupal_set_message(t('<p>Could not establish connection to the server.</p>'), 'error');
    print theme('page', '');
    return;
  }
  else {
    $xml = simplexml_load_string($xml_data);
    $xml = _yellow_simplexml2array($xml);
    return $xml;
  } 
  }



/**
 * Convert SimpleXMLElement object to array
 * Copyright Daniel FAIVRE 2005 - www.geomaticien.com
 * Copyleft GPL license
 */


function _yellow_simplexml2array($xml) {
  if (get_class($xml) == 'SimpleXMLElement') {
    $attributes = $xml->attributes();
    foreach($attributes as $k=>$v) {
      if ($v) $a[$k] = (string) $v;
    }
    $x = $xml;
    $xml = get_object_vars($xml);
  }
  if (is_array($xml)) {
    if (count($xml) == 0) return (string) $x; // for CDATA
      foreach($xml as $key=>$value) {
        $r[$key] = _yellow_simplexml2array($value);
      }
 #   if (isset($a)) $r['@'] = $a;    // Attributes
     return $r;
  }
   return (string) $xml;
}

/**
 * Ken's debug helper function
 */

function print_k($var) {
  $output = '<pre>';
  $output .= print_r($var, TRUE);
  $output .= '</pre>';
  return $output;
}