<?php
/*
Plugin Name: Head Space
Plugin URI: http://www.urbangiraffe.com/plugins/headspace
Description: HTML 'head' meta-data manager, allowing complete control over meta-data such as keywords, title, description, stylesheets, and other goodies.  The data inserted can be static text, or pulled dynamically from the details of the post.  This allows for category or user based themes,
Version: 1.1
Author: John Godley
Author URI: http://www.urbangiraffe.com
*/

$globalMeta = ABSPATH."wp-content/plugins/headspace_global.txt";


// ===============================================================
// The plugin - best not to touch much down here!
// ===============================================================

function getCategory ($matches)
{
  global $posts;
  
  // Get the categories for this post
  $cats = get_the_category ($posts[0]->ID);
  
  // matches[2] is the category value so try and access that in the array
  if ($matches[2] <= count ($cats) && $matches[2] != 0)
  {
    $val = $matches[2] - 1;
    
    if ($matches[1] == "id")
      return $cats[$val]->category_id;
    else if ($matches[1] == "desc")
      return $cats[$val]->category_description;
    else if ($matches[1] == "name")
      return $cats[$val]->category_nicename;
  }
  return "";
}

function getValues ($values)
{
  global $posts;
  
  $userData = get_userdata ($posts[0]->post_author);

  // Replace post-based items
  $searchFor = array ("/%%date%%/",
                      "/%%title%%/",
                      "/%%excerpt%%/",
                      "/%%modified%%/",
                      "/%%id%%/",
                      "/%%gid%%/",
                      "/%%nickname%%/",
                      "/%%userid%%/",
                      "/%%useremail%%/",
                      "/\n/",
                      "/\r/",
                      );
  $replaceWith = array ($posts[0]->post_date,
                        $posts[0]->post_title,
                        $posts[0]->post_excerpt,
                        $posts[0]->post_modified,
                        $posts[0]->ID,
                        $posts[0]->guid,
                        $userData->user_nickname,
                        $posts[0]->post_author,
                        $userData->user_email,
                        '',''
                        );
                        
  $values = preg_replace ($searchFor, $replaceWith, $values);
  
  // Category requires some further magic
  $values = preg_replace_callback ("/%%category(\D+)(\d+)%%/", getCategory, $values);
  return $values;
}

function doTitle ($values)
{
  // We only allow 1 title
  if (count ($values) > 0)
    echo '<title>'.$values[0].'</title>'."\n";
}

function doStyles ($values)
{
  $values = preg_replace ("/import (.*?) (.*)/", "<style type=\"text/css\" media=\"$1\">\n@import url ( $2 );\n</style>", $values);
  $values = preg_replace ("/link (.*)/", "<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" title=\"alternate\" href=\"$1\"/>", $values);
  
  foreach ($values AS $value)
    echo $value."\n";
}

function doKeywords ($values)
{
  foreach ($values AS $value)
    echo '<meta name="keywords" content="'.$value.'"/>'."\n";
}


function doDescription ($values)
{
  foreach ($values AS $value)
    echo '<meta name="description" content="'.$value.'"/>'."\n";
}

function doMeta ($values)
{
  foreach ($values AS $value)
  {
    preg_match ("/name=\"([^\"\r\n]*)\"/", $value, $names);
    preg_match ("/equiv=\"([^\"\r\n]*)\"/", $value, $equivs);
    preg_match ("/content=\"([^\"\r\n]*)\"/", $value, $content);
    
    if (count ($names) > 1 && count ($content) > 1)
    {  
      echo '<meta name="'.$names[1].'" content="'.$content[1].'"';
      if (count ($equivs) > 1)
        echo ' equiv="'.$equivs[1].'"';
      echo "/>";
    }
  }
}

function doRaw ($values)
{
  foreach ($values AS $value)
    echo $value;
}

function loadStandard (&$titles, &$styles, &$keywords, &$descriptions, &$metas)
{
  global $globalMeta;

  // Add any default values here
  if (file_exists ($globalMeta))
  {
    $file = file_get_contents ($globalMeta);

    preg_match_all ("/head_title (.*)[\n\r]*/", $file, $tmp);
    $titles = array_merge ($titles, $tmp[1]);
    preg_match_all ("/head_style (.*)[\n\r]*/", $file, $tmp);
    $styles = array_merge ($styles, $tmp[1]);
    preg_match_all ("/head_keywords (.*)[\n\r]*/", $file, $tmp);
    $keywords = array_merge ($keywords, $tmp[1]);
    preg_match_all ("/head_description (.*)[\n\r]*/", $file, $tmp);
    $descriptions = array_merge ($descriptions, $tmp[1]);
    preg_match_all ("/head_meta (.*)[\n\r]*/", $file, $tmp);
    $metas = array_merge ($metas, $tmp[1]);
  }
}

// The main function
function plugin_head_space ($dummy)
{
  // We only do a modification if this is a single page and not the main blog
  if (is_single () || is_page ())
  {
    // Is there a better way to get access to the post from wp_head?  get_post_custom_values doesnt work here
    global $posts;

    foreach ($posts AS $post)
    {
      // Get all the values for the HeadSpace stuff
      $titles       = get_post_meta ($post->ID, "head_title");
      $styles       = get_post_meta ($post->ID, "head_style");
      $keywords     = get_post_meta ($post->ID, "head_keywords");
      $descriptions = get_post_meta ($post->ID, "head_description");
      $metas        = get_post_meta ($post->ID, "head_meta");
      $raw          = get_post_meta ($post->ID, "head_raw");

      loadStandard ($titles, $styles, $keywords, $descriptions, $metas);
      
      // Handle each type of value
      doTitle       (getValues ($titles));
      doStyles      (getValues ($styles));
      doKeywords    (getValues ($keywords));
      doDescription (getValues ($descriptions));
      doMeta        (getValues ($metas));
      doRaw         ($raw);
    }
  }
}

add_filter('wp_head', 'plugin_head_space');

?>
