1<?php
2/**
3 * Gil Plugin: Shows currency equivalents
4 *
5 * @file       gil/syntax.php
6 * @brief      Shows currency equivalents
7 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
8 * @author     Luis Machuca B. <luis.machuca [at] gulix.cl>
9 * @author     Sridhar Kuppalli (concept) <sridhar.kuppalli [at] gmail.com>
10 * @version    0.4
11 *
12 *
13 *  This plugin's purpose is to display a monetary value with currency
14 *  (eg.: CLP$5 000) and provide equivalencies for other currencies
15 *  (eg.: = US$8,9 or AUD$11).
16 *
17 *  This is a plugin currently intended for **testing only**.
18 *  Only a basic form of caching is implemented and no check is done
19 *  with regards to the validity of currency units.
20 *
21 *  Original idea by Sridhar Koppalli, a developer who shows in his blog:
22 *  "Get Live currency value from yahoo server" (available at
23 * http://kuppalli.wordpress.com/2008/11/15/get-live-currency-value-using-yahoo-api/)
24 *  how to do just that using some PHP. I just adapted the literal code
25 *  to work within DokuWiki.
26 *
27 *  Greetings.
28 *        - Luis Machuca Bezzaza, 'ryan.chappelle' in the Wiki
29 *
30 */
31
32if(!defined('DW_LF')) define('DW_LF',"\n");
33
34if(!defined('DOKU_INC'))
35define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
36if(!defined('DOKU_PLUGIN'))
37define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
38require_once(DOKU_PLUGIN.'syntax.php');
39
40/**
41 * All DokuWiki plugins to extend the parser/rendering mechanism
42 * need to inherit from this class
43 */
44class syntax_plugin_gil extends DokuWiki_Syntax_Plugin {
45
46    /**
47     * Constructor. Checks for connectivity.
48     */
49    function syntax_plugin_gil(){
50      //if(!fsockopen($this->_request_uri(),80)) {
51      //  }
52      $conn = @file_get_contents ($this->_request_uri(), 0, 0, 0, 128);
53      if ($conn===false) msg('Gil Plugin: '. $this->getLang('e_nodatasrc'). '.',-1);
54      }
55
56    /**
57     * return some info
58     */
59    function getInfo(){
60      return array(
61            'author' => 'Luis Machuca Bezzaza',
62            'email'  => 'luis.machuca [at] gulix.cl',
63            'date'   => @file_get_contents(DOKU_PLUGIN . 'gil/VERSION'),
64            'name'   => 'Gil Plugin',
65            'desc'   => $this->getLang('descr'),
66            'url'    => 'http://www.dokuwiki.org/plugin:gil',
67      );
68    }
69
70    /**
71     * What kind of syntax are we?
72     */
73    function getType(){
74      return 'substition';
75    }
76
77    /**
78     * What can we Do?
79     */
80    function getAllowedTypes() {
81       return array();
82    }
83
84    /**
85     * Where to sort in?
86     */
87    function getSort(){
88      return 599;
89    }
90
91    /**
92     * What's our code layout?
93     */
94    function getPType(){
95      return 'normal';
96    }
97
98    /**
99     * How do we get to the lexer?
100     */
101    function connectTo($mode) {
102      // extended syntax (for different source currency)
103      $this->Lexer->addSpecialPattern (
104        '\$\$[A-Z]{3}[0-9]+(?:[\.,][0-9]+)?', $mode, 'plugin_gil');
105      // standard syntax
106      $this->Lexer->addSpecialPattern (
107        '\$\$[0-9]+(?:[\.,][0-9]+)?', $mode, 'plugin_gil');
108
109
110    }
111
112    /**
113     * Handle the match
114     */
115    function handle($match, $state, $pos, &$handler){
116      static $conversions;
117      // check the structure of the match:
118      $match = substr($match, 2);
119      //$cLocale= setlocale(LC_ALL, 0);
120
121      // get the plugin configuration (source and target)
122      $sc    = $this->getConf('gil_source');
123      $tc    = $this->getConf('gil_targets');
124
125      // if the first character is a letter, we are looking for a
126      // different source currency in the first 3 characters
127      if (ctype_upper($match[0])) {
128        $oc    = $sc; // original source
129        $sc    = substr($match, 0, 3);
130        $match = substr($match, 3);
131        // add original currency to targets to show
132        $tc    = $oc. ','. $tc;
133        }
134
135      // prepare targets and perform conversions
136      $tc      = explode(',', $tc);
137      foreach ($tc as $T) {
138        // request calculation
139        if (!isset($conversions[$sc][$T]) ) {
140          $tcfactor= $this->_get_curfactor($sc, $T) ;
141          $conversions[$sc][$T] = $tcfactor;
142          }
143        }
144      // finally, assemble the $data variable
145      $data= array (
146                  'state'   => $state,
147                  'match'   => $match,
148                  'source'  => $sc,
149                  'cnvs'    => $conversions
150                  );
151
152      return $data;
153    }
154
155    /**
156     * Create output
157     */
158    function render($mode, &$renderer, $data) {
159      /* get the data from $data */
160      $source_expr= $data['source']. '$'. $data['match'];
161      $convs= $data['cnvs'];
162
163      if ($mode == 'xhtml') {
164        /* the nature of this plugin should require cache disabling */
165        $renderer->info['cache'] = false;
166        $title_expr     = "Gil conversions for $source_expr.";
167        $cnv_expr       = $this->_do_conv_text($convs, $data['match'], $data['source']);
168        $renderer->doc .= <<<EOF
169<span class="gil" title="$title_expr">$source_expr <span data="gil:conversions" class="tooltip">$cnv_expr</span></span>
170EOF;
171        return true;
172        }
173      else if ($mode == 'text') {
174        /* here we simply throw the conversions together */
175        $renderer->doc.= $source_expr;
176        $renderer->doc.= ' '. $this->_do_conv_text($convs, $data['match']);
177        $renderer->doc.= ' ';
178        return true;
179        }
180      return false;
181    }
182
183    /**
184     * from this point onwards, helper functions
185     */
186
187
188    /**
189     * @fn     _get_curfactor
190     * @brief  Obtains the currency conversion factor
191     *
192     * This is pretty much Sridhar's original work.
193     */
194    function _get_curfactor ($sc, $tc) {
195      $hpool= '';
196      $query= $this->_request_uri();
197      $query= str_replace('$1', $sc, $query);
198      $query= str_replace('$2', $tc, $query);
199      // request the data conversion sheet
200      $handle= @fopen($query, 'r');
201      if (!$handle) {
202        //printf ($this->getLang('e_nodatasrc'));
203        $ans= 'N/A';
204        }
205      else {
206        $hpool= fgets($handle, 2048);
207        // retrieve the latest data
208        if (empty($hpool) ) {
209          // error handling is not yet appropiate
210          $ans= '?';
211          }
212        else {
213          $matches= explode (',', $hpool);
214          $factor= $matches[1];
215          $ans= floatval($factor);
216          }
217        } // end process input
218      fclose($handle);
219      return $ans;
220      } // end function
221
222
223    /**
224     * @fn     _do_conv_text
225     * @brief  Creates a single text string from the conversions $convs.
226     *
227     */
228    function _do_conv_text ($convs, $a, $sc) {
229      $text= '';
230      $ctext= array();
231      foreach ($convs[$sc] as $K => $M) {
232        $ctext[]= "$K". ' '. $M*$a;
233        }
234      // join everything into a single string
235      $text= '( '. implode(' | ', $ctext). ' )';
236      return $text;
237      } // end function
238
239    function _request_uri () {
240      static $url= 'http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s=$1$2=X';
241      return $url;
242      }
243
244
245}
246