<?php // Copyright Bobbing Wide 2009-2013
// bobbfunc.inc

/** 
 * Return the plugin version of the oik base plugin
 * @return string $version e.g. 2.0-alpha, 2.0-RC1, 2.0, 2.0.mmdd 
 */
function bw_oik_version() { 
  oik_require( "admin/oik-plugins.inc" );
  $version = bw_get_plugin_version();
  return( $version );
  // return( '2.0-RC1' );
}

require_once( "oik_boot.inc" );   /* Don't use oik_require here */

/**
 * bw API partial equivalent of PHP's output buffering
 * 
 * Note: this isn't really an output buffer
 * Use bw_push() and bw_pop() if you need to stack buffers during nested processing.
 * $bwecho is used by the bw APIs to create the HTML output that is then returned from the shortcode functions  
 * 
*/
function bw_echo( $string ) {
  global $bwecho;
  $bwecho.=$string;
}

/**
 * Use bw_flush() to echo the contents of $bwecho then empty it
 * 
 * You may need to use this before calling a WordPress function that echoes its output 
 * directly rather than through a buffer. e.g. before calling settings_fields()
 */
function bw_flush() {
  global $bwecho;
  echo $bwecho;
  //bw_trace( "inside bw_flush" );
  //bw_trace( $bwecho );
  //bw_trace( "after" );
  $bwecho = NULL;
  // bw_backtrace();
}

/**
 * Use bw_ret() to return the contents of $bwecho, leaving the global value as NULL
 */
function bw_ret() {
  global $bwecho;
  $bwret = $bwecho;
  $bwecho = NULL;
  //bw_trace( __FUNCTION__ );
  return( $bwret );
}

/**
 * Push then empty the current $bwecho buffer
*/ 
function bw_push() {
 global $bwecho, $bwecho_array;
 $bwecho_array[] = $bwecho;
 $bwecho = null;
}

/** 
 * Restore the previous $bwecho buffer
*/
function bw_pop() {
  global $bwecho, $bwecho_array;
  $bwecho = array_pop( $bwecho_array ); 
}   

/**
 * Perform nested shortcode expansion
 *
 * @param string $content - the content to be expanded
 * @return string the content after shortcode expansion
 *
 * Performance question - is there any point testing for a '[' in the string? i.e. How expensive is do_shortcode() ? 
 */
function bw_do_shortcode( $content ) {
  bw_push(); 
  $content = do_shortcode( $content );
  bw_pop(); 
  return( $content );
}

/**
 * Return an image tag
 * 
 * @param string $class  CSS classes for this image
 * @param string $jpg file name of the image (src=)
 * @param string $title value for the title= and alt= attributes
 * @param string $width width of the image
 * @param string $height height of the image
 * @return string HTML of the img tag
 
 * Note: This function does not handle an id= attribute
 */
function retimage( $class, $jpg, $title=NULL, $width=NULL, $height=NULL, $extras=null ) {
  $img = '<img class="' .  $class . '" ';  
  $img .= 'src="' .  bw_expand_link( $jpg ) . '" ';
  if ( !is_null( $width))
    $img .= 'width="' . $width . '" ';
  if ( !is_null( $height))
    $img .= 'height="' . $height . '" ';
  if ( !is_null( $title ) ) {
    $title = strip_tags( $title );
    $img .= 'title="' . $title . '" ';
    $img .= 'alt="' . $title . '" ';
  } 
  if ( $extras ) { 
    $img .= $extras; 
  }
  $img .= " />";
  return( $img );
}
 
function image( $class, $jpg, $title=NULL, $width=NULL, $height=NULL ) {
  $img = retimage( $class, $jpg, $title, $width, $height ); 
  bw_echo( $img );
}

function kv( $keyword, $value=null ) {
  if ( $value != null ) {
    $kv = ' '.$keyword . '="' . $value .'"';
  } else {
    $kv = '';
  }  
  return( $kv );  
} 

function atitle( $title = NULL ) {
  $title = wp_strip_all_tags( $title );
  return( kv( "title", $title ) );
} 

/**
 * Create an anchor tag for linking within a page
 */ 
function aname( $name ) { 
  stag( 'a' );
  e( ' name="'. $name . '"' );
  etag( 'a' );
  // return( bw_ret() );
} 

/**
 * Create a link
 * 
 * @param string $class - the classes for the anchor tag
 * @param string $url - the fully formed URL e.g. http://www.oik-plugins.com
 * @param string $linktori - is the text or image
 * @param string $alt - if NULL will use $linktori
 * @param string $id - the unique ID for the anchor tag
 * @param string $extra - anything else that needs to go in the <a> tag. e.g. 'onclick=then some javascript' 
 *
 * @uses retlink()
 * 
*/   
function alink( $class=NULL, $url, $linktori=NULL, $alt=NULL, $id=NULL, $extra=NULL ) {
  $link = retlink( $class, $url, $linktori, $alt, $id, $extra );
  e( $link ); 
}

/**
 * Return a well formed link
 *
 * Parameters as for alink()
*/
function retlink( $class=NULL, $url, $linktori=NULL, $alt=NULL, $id=NULL, $extra=NULL  ) {
  if ( is_null( $linktori ) )
    $linktori = $url;
  $link = "<a" ;
  $link .= kv( "class", $class ); // aclass( $class );
  $link .= kv( "id", $id ); // aid( $id );
  $link .= kv( "href", $url ); // ahref( $url );
  if ( is_null( $alt ) )
     $alt = $linktori;
  // Is alt= allowed with XHTML Strict 1.0?    
  // aalt( $alt );
  $link .= atitle( $alt );
  if ( $extra )
    $link .= $extra ;
  $link .= ">";
  if ( $linktori )
    $link .= $linktori;
  $link .= "</a>";
  return( $link );
}  
 
/**
 * Return an HTML opening tag
 * 
 * @param string $tag - the HTML tag. e.g. span
 * @param string $class - CSS classes
 * @param string $id - unique ID
 * @param string $extra - additional fields formatted using kv()
 * @return string an HTML opening tag
 */
function retstag( $tag, $class=NULL, $id=NULL, $extra=NULL ) {   
  $stag = '<' . $tag ;
  if ( $class <> NULL )
     $stag.= ' class="' . $class. '"';
  if ( $id <> NULL )
     $stag.= ' id="' . $id. '"';
  if ( $extra <> NULL )
    $stag .= ' '. $extra;   
  $stag.= '>';
  return( $stag );
}


/**
 * Return a start tag if the class is not null 
 */
function nullretstag( $tag, $class=NULL ) {
   $ret = '';
   if ( $class <> NULL )
      $ret = retstag( $tag, $class );
   return( $ret );     
} 


/**
 * Output an HTML opening tag
 *
 * The tag is written to the internal buffer
 * 
 * @param string $tag - the HTML tag. e.g. span
 * @param string $class - CSS classes
 * @param string $id - unique ID
 * @param string $extra - additional fields formatted using kv()
 * 
 */
function stag( $tag, $class=NULL, $id=NULL, $extra=NULL ) {
  bw_echo( retstag( $tag, $class, $id, $extra ));
}

/**
 * Start an ordered list
 */
function sol( $class=NULL, $id=NULL ) {
   stag( "ol", $class, $id );
}        

/** 
 * Start an unordered list
 */ 
function sul( $class=NULL, $id=NULL, $extra=null ) {
   stag( "ul", $class, $id, $extra );
} 

/**
 * Start a div
 */       
function sdiv( $class=NULL, $id=NULL, $extra=NULL ) {
   stag( "div", $class, $id, $extra );
}

/** 
 * End an ordered list
 */
function eol() {
   bw_echo( '</ol>' );
}
 
/**
 * End an unordered list
 */  
function eul() {
   bw_echo( '</ul>' );
}

/** 
 * End a div
 */
function ediv() {
   bw_echo( '</div>' );
}

/**
 * Create a dummy div which may be used for placing graphics using background images in CSS 
 */
function sediv( $class=NULL, $id=NULL, $extra=NULL ) {
 sdiv( $class, $id, $extra );
 ediv();
}   

/**
 * End a paragraph (p) tag
 */
function ep() {
  bw_echo( '</p>' );
}

/** 
 * Return an end tag if the class is not null 
 * 
 * @see nullretstag()
 */
function nullretetag( $tag, $class=NULL ) {
  $ret = '';
  if ( $class <> NULL )
     $ret = retetag( $tag );
  return( $ret );   
}

/**
 * Return an end tag 
 */
function retetag( $tag ) {
   return( '</'.$tag.'>');
}  

/** 
 * Output an end tag
 */
function etag( $tag ) {
  //  bw_echo( '</'.$tag.'>'."\n";
  bw_echo( '</'.$tag.'>' );
}    

/**
 * Start a paragraph
 * 
 * @see sp()
 */
function sp( $class=NULL, $id=NULL ) {
   stag( "p", $class, $id );
} 

/**
 * Output a paragraph of text 
 */
function p( $text=NULL, $class=NULL, $id=NULL ) {
  sp( $class, $id );
  if ( !is_null( $text ))
    bwt( $text );
  etag( "p" );
}

function hn( $text, $level, $class, $id ) {
   stag( "h".$level, $class, $id );
   bwt( $text );
   etag( "h".$level );
}

function h1( $text, $class=NULL, $id=NULL ) {
   hn( $text, "1", $class, $id ); 
}

function h2( $text, $class=NULL, $id=NULL ) {
   hn( $text, "2", $class, $id );  
}

function h3( $text, $class=NULL, $id=NULL ) {
   hn( $text, "3", $class, $id ); 
}

function h4( $text, $class=NULL, $id=NULL ) {
   hn( $text, "4", $class, $id ); 
}

function h5( $text, $class=NULL, $id=NULL ) {
   hn( $text, "5", $class, $id ); 
}

function h6( $text, $class=NULL, $id=NULL ) {
   hn( $text, "6", $class, $id ); 
}


/** Function e() replaces the original t() function used in Bobbing Wide custom code
 *   since for Drupal t() is already defined for translatable text
 *  Function bwt() does a similar job but also performs some strange filtering if required.
 */  
function bwt( $text = NULL ) {
  global $bbboing;  

  if ( !is_null( $text ))
  {
    if ( $bbboing )
       bw_echo( $bbboing( $text ));
    else
      bw_echo( $text ) ;
  }    
}

/**
 * @func e for bw_echo( if not NULL
 */
function e( $text = NULL ) {
  if ( !is_null( $text ))
    bw_echo( $text );
}

/** 
 * Produce a break tag with optional text to follow
 */
function br( $text=NULL ) {
   bw_echo( '<br />' );
   bwt( $text ); 
}   

/**
 * Produce a horizontal rule tag
 */
function hr() {
  bw_echo( '<hr />' );
}  
  

/**
 * Create a list item with a specific CSS class and/or ID
 */
function lit( $text, $class=NULL, $id=NULL ) {
  stag( "li", $class, $id );
  bwt( $text );
  etag( "li" );
}

/** 
 * Helper function for list item 
 */
function li( $text ) {
  lit( $text );   
} 

// Note: here we omit the 's' of span to make it easier to type
function span( $class=NULL, $id=NULL ) {
  stag( "span", $class, $id );
}

function epan() {
  etag( "span" );
}  

function sepan( $class=NULL, $text=NULL ) {
  span( $class );
  e( $text );
  epan();
}

/**
 * Output a table data field
 */
function td( $data, $class=NULL, $id=NULL ) {
  stag( "td", $class, $id );
  e( $data );
  etag( "td" );
} 

/**
 * Output a table heading
 */
function th( $data, $class=NULL, $id=NULL ) {
  stag( "th", $class, $id );
  e( $data );
  etag( "th" );
}         

// This routine finds the subdirectory under which this local version of the website is installed
// we need to remove this from index lookups but add it to links! 
// Example: on betterbfar in the twentyte directory it's set:
// $docroot_suffix = "/twentyte/" ;

function bw_get_docroot_suffix() {
  bw_backtrace();
  //gobang();
  $docroot_suffix = "/";
  if ( $_SERVER['SERVER_NAME'] == bw_get_option( "betterbyfar") )
  {
     $exdr = explode( '/', $_SERVER["DOCUMENT_ROOT"] );
     $exsf = explode( '/', $_SERVER['SCRIPT_FILENAME'] );
     
     $docroot_suffix = '/' . $exsf[ count( $exdr) ] . '/';
     
     // bw_debug( "_SERVER[DOCUMENT_ROOT]: " . $_SERVER["DOCUMENT_ROOT"] );
     // bw_debug( "_SERVER[REQUEST_URI]: " .  $_SERVER['REQUEST_URI'] );  
     // bw_debug( "_SERVER[SCRIPT_FILENAME]: " . $_SERVER['SCRIPT_FILENAME'] );
  
     // bw_debug( "docroot_suffix: " . $docroot_suffix );
  }
  return( $docroot_suffix );
}

/* This gets us to the right place when the link is from a sub-directory
   but it doesn't add anthing when the link is of form
     http:
     https:
     ftp:
     mailto: 
*/     
function bw_expand_link( $linkurl ) {
   if ( strpos( $linkurl, ':' ) == 0  )
      $linkurl = bw_get_docroot_suffix() . $linkurl;
   return( $linkurl) ;   
}

function strong( $text, $class=NULL, $id=NULL ) {
   stag( "strong", $class, $id ) ;
   e( $text );
   etag( "strong" );    
}

function em( $text, $class=NULL, $id=NULL ) {
   stag( "em", $class, $id ) ;
   e( $text );
   etag( "em" );    
}

function blockquote( $text, $class=NULL, $id=NULL ) {
   stag( "blockquote", $class, $id ) ;
   e( $text );
   etag( "blockquote" );    
}

/**
 * Produce a quotation tag
 */
function bw_quote( $text, $class=NULL, $id=NULL ) {
   stag( "quote", $class, $id ) ;
   e( $text );
   etag( "quote" );    
}

function cite( $text, $class=NULL, $id=NULL ) {
   stag( "cite", $class, $id ) ;
   e( $text );
   etag( "cite" );    
}

/** 
 * Create an <abbr> tag 
 */
function abbr( $title="Often Included Key-information wide", $abbrev="oik" ) {
  if ( $abbrev ) {
    $abbr = '<abbr title="';
    $abbr .= $title;
    $abbr .= '">';
    $abbr .= $abbrev; 
    $abbr .= '</abbr>';
    e( $abbr );
  }  
}
 
/** 
 * Create an <acronym> tag 
 * Note: acronym becomes obsolete in HTML5
 */
function acronym( $title="Often Included Key-information wide", $acronym="oik" ) {
  if ( $acronym ) {
    $acro = '<acronym title="';
    $acro .= $title;
    $acro .= '">';
    $acro .= $acronym; 
    $acro .= '</acronym>';
    e( $acro );
  }  
} 


  
function c( $text ) {
  bw_echo( '<!--' . $text . '-->' );
} 

function bw_debug_on() {
  global $bw_debug_on;
  $bw_debug_on = TRUE;
}

function bw_debug_off() {
  global $bw_debug_on;
  $bw_debug_on = FALSE;
}     
     

function bw_debug( $text ) {
  global $oktop, $bw_debug_on;
  if ($bw_debug_on)
  {
    if ( $oktop )
      p( $bw_debug_on . $text );
    else
      c( $text ); 
  }     
}


/* Function: bw_image_link
   Purpose: To display an image as a link 
*/   
function bw_image_link( $link 
                      , $image
                      , $imagetext
                      , $width=302
                      , $height=227
                      ) {
  $linktext = bw_get_linktext( $link );
  $a = '<a title="';
  $a.= $linktext;
  $a.= '" href="';
  $a.= bw_expand_link( $link );
  $a.= '">';
  bw_echo( $a . "\n" );
  
  image( ""
       , $image
       , $imagetext
       , $width
       , $height
       );
  etag( "a" );
 
} 



function bw( $bw_class_prefix=NULL ) {  
  if ( is_array( $bw_class_prefix ) ) {
    $bwcp = bw_array_get( $bw_class_prefix, "cp", null);
    $cp = ' class="' . $bwcp;
  } else {   

      if ( is_null( $bw_class_prefix )) 
         $cp = ' class="';
      else
         $cp = ' class="' . $bw_class_prefix;
  }         
      $bw  = '<em' .$cp .'bw_b1">B</em>';
      $bw .= '<em' .$cp .'bw_o">o</em>'; 
      $bw .= '<em' .$cp .'bw_b2">b</em>';
      $bw .= '<em' .$cp .'bw_b3">b</em>';
      $bw .= '<em' .$cp .'bw_i1">i</em>';
      $bw .= '<em' .$cp .'bw_n">n</em>';
      $bw .= '<em' .$cp .'bw_g">g</em>';
      $bw .= '<em' .$cp .'bw_space">&nbsp;</em>';
      $bw .= '<em' .$cp .'bw_W">W</em>';
      $bw .= '<em' .$cp .'bw_i2">i</em>';
      $bw .= '<em' .$cp .'bw_d">d</em>';
      $bw .= '<em' .$cp .'bw_e">e</em>';
      
         
      return $bw;
}


  

  
//function ebw( $bw_class_prefix=NULL ) {
//     bw_echo( bw( $bw_class_prefix ) );
//}

/** 
 * echo Bobbing Wide inside a theme's template file
 */
function ebw( $bw_class_prefix=NULL )
{
   echo bw( $bw_class_prefix );
}

require_once( "bobbcomp.inc" );

if ( bw_is_wordpress() ) {
  /**
    * In WordPress Artisteer provides code to deal with buttons
    * but in Drupal it needs more wrapping.
    */
  function art_button( $linkurl, $text, $title=NULL, $class=NULL  ) {
    alink( "button " . $class , $linkurl, $text, $title ) ;
  }
}
else {
  function art_button( $linkurl, $text, $title=NULL, $class=NULL  ) {
    span("art-button-wrapper" );
    sepan("art-button-l l");
    sepan("art-button-r r");
    alink( "button art-button " . $class , $linkurl, $text, $title ) ;
    epan();
  }
}



/*  default logic
  set a default value if the value is not set
*/
function bw_default( $value, $default=NULL ) {
  $val = $value; 
  bw_trace( $val, __FUNCTION__, __LINE__, __FILE__, "value before" );
  if ( empty( $val ))
    $val = $default;
  bw_trace( $val, __FUNCTION__, __LINE__, __FILE__, "value returned" );
  return( $val );
}    
  
/* 
  Gallery logic
  
  The gallery shortcode allows media to be displayed
  Here we take values from the page's metadata
   gallery-columns = 1,2, etc
   gallery-size = 'thumbnail', 'medium', 'large', 'full'
  and apply them to the gallery shortcode
  If the meta data is not set in the post the default values are:
  
  
  [gallery columns="1" size="medium"] 
  
  For more information on gallery see http://codex.wordpress.org/Gallery_Shortcode
  For more information on sizes see WordPress admin panel under Settings > Media
  
*/
function bw_gallery() {
  c( "gallery processing");
  global $post;
  bw_trace( $post, __FUNCTION__, __LINE__, __FILE__, "post" );
 
  $columns = get_post_meta( $post->ID, "gallery-columns", true );
  $columns = bw_default( $columns, "1");
  $size = get_post_meta( $post->ID, "gallery-size", true );
  $size = bw_default( $size, "medium" );
   
  $gallery_options = array( 'columns' => $columns, 'size' => $size );
  e( gallery_shortcode( $gallery_options ));
}

/**
 * Format a date with the specified format
 *
 * @param string $date - either a number - representing the UNIX date or a recognisable date string or NULL - for the current date
 *  e.g. 1293840000 => 2011-01-01
 *       2011-12-31 => 2011-12-31
 * @param string $format - date formatting string
 * @returns string $date - the date formatted according to the $format string 
 *
 * A value of NULL will be returned as NULL
 *
 * strtotime() works for dates NOT in format yyyy-mm-dd e.g. '5-10-1955' or '30 Jul 1958'
 * Note: Dates before 1970-01-01 are stored as negative values.
 *
 */
function bw_format_date( $date=NULL, $format="Y-m-d" ) {
  if ( $date != NULL ) {
    $date = trim( $date );
    if ( !is_numeric( $date ) ) {
      $date = strtotime( $date );
    } 
    $date = date( $format, $date );
    // bw_trace2( $date, "date" );
  } else {
    $date = date( $format );
  }  
  return( $date );
}

/**
 * Validate as true or false
 * 
 * Simple function to validate a field as TRUE or FALSE given a big list of strings that represent TRUE 
 *
 * @param string $field - value to be validated. If null then the value returned is FALSE
 * @param string $trues - list of TRUE values. Now includes "on" to allow for checkbox fields
 * @param string $falses - list of FALSE values  Note: No need for the $falses parameter at present
 * @return bool true or false
 */
function bw_validate_torf( $field, $trues=",true,yes,1,on", $falses=NULL ) {
  $torf = FALSE;
  if ( $field ) {
    $field = ",".strtolower( $field );
    //bw_trace( $field, __FUNCTION__, __LINE__, __FILE__, "field" );
    //bw_trace( $trues, __FUNCTION__, __LINE__, __FILE__, "trues" );
    $pos = strpos( $trues, $field );
    //bw_trace( $pos, __FUNCTION__, __LINE__, __FILE__, "pos" );
    if ( $pos !== FALSE )
      $torf = TRUE;
  }    
  return( $torf );
}

/** 
 * Return what might be the plugin name with hyphens and lowercase chars
 * 
 * Strip any tags - the WordPress UI likes adding <br />'s where we don't want them
 */
function bw_plugin_namify( $name ) {
  $name = trim( $name );
  $name = str_replace( ' ', '-', $name );
  $name = str_replace( '_', '-', $name );
  $name = strtolower( $name );
  return( bw_trace2( $name ) ); 
}
  
/**
 * Return the function name of the function to invoke built from parms
 *
 * @param string $prefix - the function name prefix e.g. "_bw_create_content"
 * @param string $key - the multi-word key e.g. About oik-plugins"
 * @return string $funcname - the function name to invoke
 * 
 * Example: Return the function name to create content for an about us page
 * $funcname = bw_funcname( "_bw_create_content", "About oik-plugins" );
 * 
 * Would return the most detailed function that exists
 *  _bw_create_content
 *  _bw_create_content_about
 *  _bw_create_content_about_oik
 *  _bw_create_content_about_oik_plugins
 *
 * Note: In the original version of this code it happily produced
 * _sc_help_caption
 * for wp_caption
 * So check what happens in the setup plugin **?**
*/
function bw_funcname( $prefix, $key, $value=NULL ) {
  $funcname = $prefix; 
  $testname = $funcname;
  $keys = explode( "-", bw_plugin_namify( $key ));
  foreach ( $keys as $keyword ) {
    $testname .= '_'.$keyword;
    bw_trace2( $testname, "testname", false );
    if ( function_exists( $testname ) ) {
      $funcname = $testname;
    }  
  }
  return( $funcname );
} 

/**
 * Return the URL for a resource file
 * 
 * @param string $file - the name of the file within the plugin - leading '/' omitted
 * @param string $plugin - the plugin's stub
 * @return string fully qualified URL to the resource file
 * 
 * @uses plugin_dir_url() to find the plugin base directory then appends the plugin folder and file name
 */
function oik_url( $file=null, $plugin='oik' ) {
  $url = plugin_dir_url( null );
  $url .= "$plugin/$file" ;
  return( $url ); 
}

/**
 * Need to find out more about other shortcodes and 
 * then find a way of capturing the registration information for a shortcode
 * it should be possible to find the plugin that implements the shortcode
 * but we might not know the location of the function that we can call 
 * if the shortcode is a lazy shortcode.
 */
function bw_sc_help( $shortcode="oik" ) {
  oik_require( "includes/oik-sc-help.inc" );
  bw_lazy_sc_help( $shortcode );
}

function bw_sc_syntax( $shortcode="oik" ) {
  oik_require( "includes/oik-sc-help.inc" );
  bw_lazy_sc_syntax( $shortcode );
}

function bw_sc_example( $shortcode="oik", $atts=null ) {
  oik_require( "includes/oik-sc-help.inc" );
  bw_lazy_sc_example( $shortcode, $atts );
}

function bw_sc_snippet( $shortcode="oik" ) {
  oik_require( "includes/oik-sc-help.inc" );
  bw_lazy_sc_snippet( $shortcode );
}

/**
  * Dynamic jQuery setting the selector, function and option parameters
  * When should we use?
  * 
  * jQuery(window).load(function() - when you need to wait for images to load?
  * jQuery(function()
  * jQuery(document).ready(function()
  *
*/  
if ( !function_exists( "bw_jquery" ) ) {
function bw_jquery( $selector, $method, $parms=null, $windowload=false ) {
  bw_jq( "<script type=\"text/javascript\">" );
  if ( $windowload ) {
    $jqfn = "jQuery(window).load(function()";
  } else {
    $jqfn = "jQuery(document).ready(function()"; 
  }    
  $function = "$jqfn { jQuery( \"$selector\" ).$method( $parms ); });";
  bw_jq( $function );
  bw_jq( "</script>" );
} 
}


/**
 * Flush the inline jQuery code to the WordPress footer 
 * @globals bw_jq
 */
function bw_jq_flush() {
  global $bw_jq;
  echo $bw_jq;
  $bw_jq = null;
}  


function bw_jq( $text ) {
  global $bw_jq;
  if ( !isset( $bw_jq ) ) {
    wp_enqueue_script( 'jquery' ); 
    if ( !is_admin() ) {
      add_action( 'wp_footer', "bw_jq_flush", 25 );
    }  
    //bw_trace2( $bw_jq, "bw_jq not set" );  
  }
  $bw_jq .=$text;
  //bw_trace2( $bw_jq, "bw_jq", false );  

  if ( is_admin() ) {
    bw_jq_flush();
  }  
}



/**
 * json_encode without Warnings
 *
 * JSON_NUMERIC_CHECK was added in PHP version 5.3.3
 * Here we may need to perform our own numeric conversion to strip out the damage done by json_encode 
 * if the PHP version is earlier than this. **?** Not implemented yet! 
 *
 */
function bw_json_encode( $parms, $option=null ) { 
  if ( version_compare( PHP_VERSION, "5.3.3", "<" ) ) {
    $json = json_encode( $parms );
  } else {
    $json = json_encode( $parms, $option );
  }
  
  return( $json ); 
} 

/**
 * Format an array of parms for jQuery 
 * 
 * If it's not an array we treat it as an already formatted string
 * OR a single parameter and value
 *
 * @uses json_encode() which by default encloses numeric values as string, which can cause problems for some jQuery code
 * (e.g. jQuery Nivo slider) SO we pass the JSON_NUMERIC_CHECK option to prevent this.
*/
if ( !function_exists( "bw_jkv" ) ) {

function bw_jkv( $parms, $value=null, $json_options=null ) {
  if ( is_array( $parms ) ) {
    bw_jtorf( $parms );
    if ( $json_options == null && defined( JSON_NUMERIC_CHECK )) {
      $json_options = (JSON_NUMERIC_CHECK | JSON_FORCE_OBJECT);
    }
    $jqoption = bw_json_encode( $parms, $json_options );
  } else {
    $jqoption = "{";
    if ( $value ) { 
      $jqoption .= "$parms : $value";
    } else {
      $jqoption .= $parms;
    }  
    $jqoption .= "}";
  }
  //bw_trace2( $jqoption, "jqoption" );
  return( $jqoption );
}
}

/**
 * Pre-processing for json_encode to convert
 * "on" == "true" to 1 == true
 * "off" == "0" to 0 == false
 * torf = true or false
 * This will allow WordPress options which are checkboxes to be passed as jQuery boolean parameters
 * where the default is true so we need to pass false.
 * Used in conjunction with a hidden field for checkboxes.
 *
 * This code also removes any entries where the option value is blank...
 * allowing the jQuery code to use its hardcoded default.
 * 
*/
if ( !function_exists( "bw_jtorf" ) ) {

function bw_jtorf( &$parms ) {
  foreach ( $parms as $parm => $value ) {
    if ( $value == "on" ) {
      $parms[$parm] = 1;
    } elseif ( $value == "0" ) {
      $parms[$parm] = 0;
    } elseif ( $value == "" ) { 
      unset( $parms[$parm] );  
    }    
  }
  //bw_trace2();
}
}

/**
 * Convert a simple array into an associative array keyed on the value
 * @param array $array - a simple array - with at least one entry
 * @return array $assoc_array
*/ 
function bw_assoc( $array ) {
  $assoc_array = array();
  foreach ( $array as $key => $value  ) {
    $assoc_array[$value] = $value;
  }
  return( $assoc_array );
}    

/**
 *  Convert array of file names to array of urls
 *
 * @param array $files - array of file names 
 * @param array $atts - attributes for get_post
 * @return array $urls
 * 
 * We filter the results to take into account SOME of the possible parameters:
 * 
 * 'numberposts' - we accept ALL by default 
 *   'offset' - start from the first by default 
*/ 
function bw_file_to_url( $files, $atts=null ) {
  $offset = bw_array_get( $atts, 'offset', 0 );
  $numberposts = bw_array_get( $atts, "numberposts", count( $files ) );
  $urls = array();
  if ( count( $files ) ) {
    foreach( $files as $file ) {
      if ( ( $offset <= 0 ) && ( $numberposts > 0 ) ) {
        $urls[] = plugin_dir_url( $file ) . basename( $file );
      }  
      $offset--;
      $numberposts--;
    }
  }  
  bw_trace2( $urls );
  return( $urls );
}    

/** 
 * Return the URL that this image links to
 * @param int $postid - ID of the attachment
 * @return string $permalink URL for the link
 */
function bw_get_image_link( $postid ) {
  $permalink = get_post_meta( $postid, "_bw_image_link", true );    
  if ( !$permalink ) {
    $permalink = get_permalink( $postid );
  }
  return( $permalink );
}

/**
 * Recreate a WordPress option with the defined autoload value 
 * @param string $option name
 * @param string $autoload value: 'yes'|'no'. default='no' 
 * @return $options 
 * 
 * See 978-0-470-91622 p. 168 for the inspiration
 */
function bw_recreate_options( $option, $autoload="no" ) {
  $options = get_option( $option );   
  if ( $options !== FALSE ) {    
    delete_option( $option );
  }
  add_option( $option, $options, null, $autoload );
  bw_trace2( $options );
  return( $options );
} 

/**
 * Return a non null string following the separator or null 
 * @param string $value - if null we return null
 * @param string $sep - separating string
 * @return null or $sep followed immediately by $value
 */
function bw_append( $value=null, $sep=" " ) {
  if ( $value ) 
    $value = $sep . $value;
  return $value;  
}

/**
 * This is very much like bw_default but it uses trim() to strip blanks
 * Can we change bw_default to do the same?
 */
function bw_pick_one( $preferred, $alternate ) {
  $picked = trim( $preferred );
  //bw_trace2( "!$picked!", "picked preferred" );
  if ( !$picked  ) {
    $picked = trim( $alternate );
    
    //bw_trace2( $picked, "picked alternate" );
  }
  return( $picked );
}

/**
 * Load the language specific stuff for "oik"
 *
 * @link http://codex.wordpress.org/Function_Reference/load_plugin_textdomain
 * If the path is not given then it will be the root of the plugin directory.
 */
function bw_load_plugin_textdomain( $domain="oik" ) {
  load_plugin_textdomain( $domain, false, dirname( plugin_basename(__FILE__)).'/languages/' );
}  

/**
 * Return the current theme name
 * 
 * Note: get_current_theme() was deprecated in WP 3.4 but wp_get_theme() is NEW
 * It didn't exist in WP 3.3.1.
 * So we need a wrapper to test the WordPress version
 * 
 
C:\apache\htdocs\wordpress\wp-content\plugins\oik\bobbfunc.inc(1037:0) 2012-07-18T11:03:12+00:00 617 cf=the_content bw_get_theme(4) current theme WP_Theme Object
(
    [theme_root:WP_Theme:private] => C:\apache\htdocs\wordpress/wp-content/themes
    [headers:WP_Theme:private] => Array
        (
            [Name] => Twenty Eleven
            [ThemeURI] => http://wordpress.org/extend/themes/twentyeleven
            [Description] => The 2011 theme for WordPress is sophisticated, lightweight, and adaptable. Make it yours with a custom menu, header image, and background -- then go further with available theme options for light or dark color scheme, custom link colors, and three layout choices. Twenty Eleven comes equipped with a Showcase page template that transforms your front page into a showcase to show off your best content, widget support galore (sidebar, three footer areas, and a Showcase page widget area), and a custom "Ephemera" widget to display your Aside, Link, Quote, or Status posts. Included are styles for print and for the admin editor, support for featured images (as custom header images on posts and pages and as large images on featured "sticky" posts), and special styles for six different post formats.
            [Author] => the WordPress team
            [AuthorURI] => http://wordpress.org/
            [Version] => 1.4
            [Template] => 
            [Status] => 
            [Tags] => dark, light, white, black, gray, one-column, two-columns, left-sidebar, right-sidebar, fixed-width, flexible-width, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-image-header, featured-images, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready
            [TextDomain] => twentyeleven
            [DomainPath] => 
        )

    [headers_sanitized:WP_Theme:private] => 
    [name_translated:WP_Theme:private] => 
    [errors:WP_Theme:private] => 
    [stylesheet:WP_Theme:private] => twentyeleven
    [template:WP_Theme:private] => twentyeleven
    [parent:WP_Theme:private] => 
    [theme_root_uri:WP_Theme:private] => 
    [textdomain_loaded:WP_Theme:private] => 
    [cache_hash:WP_Theme:private] => a3e6a9c1d55ef4070d99b81dc839928b
)
 * 
 */
function bw_get_theme() { 
  global $wp_version;
  if ( version_compare( $wp_version, '3.4', "ge" ) ) {
    $theme = wp_get_theme();
    $current_theme = $theme->stylesheet;  
  } else {
    $current_theme = get_current_theme();
  }  
  bw_trace2( $current_theme, "current theme" );
  return( $current_theme );
}    

function bw_wp_error( $code, $text=null, $data=null ) {
  oik_require( "includes/bw_error.inc" );
  return( bw_lazy_wp_error( $code, $text, $data ) );
}  
