Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/mvc/helpers/tools

[return to app]
1 <?php
2
/**
3  * 3rd Party tools helper
4  */
5
class toolsHelper {
6     
/**
7      * Returns the URL of a Facebook profile
8      *
9      * @param int $id Facebook ID
10      * @return string
11      */
12     
public function facebookProfileUrl($id) {
13         return 
'http://www.facebook.com/profile.php?id=' $id;
14     }
15
16     
/**
17      * Returns the URL to a Facebook users photo
18      *
19      * @param int $id Facebook ID
20      * @param string $type Default: square (50px * 50px) Facebook Graph size identifiers; other valid options are
21      *                     small (50px wide, variable height) and large (about 200 pixels wide, variable height)
22      * @return string
23      */
24     
public function facebookPhotoUrl($id$type 'square') {
25         return 
'http://graph.facebook.com/' $id '/picture?type=' $type;
26     }
27
28     
/**
29      * Creates an embedded YouTube video
30      *
31      * @param mixed $args
32      * @return string
33      */
34     
public function youtube($args) {
35         if (!
is_array($args)) {
36             
$args = array('id' => $args);
37         }
38         
$id str_replace('http://www.youtube.com/watch?v='''$args['id']);
39         
$url 'http://www.youtube.com/v/' $id '&amp;hl=en&amp;fs=1';
40         
$defaultWidth 425;
41         
$defaultHeight 344;
42         if (isset(
$args['format'])) {
43             
$formats = array('normal' => 6'mobile' => 17'high' => 18'720p' => 22'1080p' => 37);
44             
$format = (isset($formats[$args['format']]) ? $formats[$args['format']] : $args['format']);
45             
$url .= '&amp;fmt=' $format;
46             if (
$format 17) {
47                 
$defaultWidth 854;
48                 
$defaultHeight 505;
49                 if (
$format 21) {
50                     
$url .= '&amp;hd=' . (!isset($args['hd']) ? $args['hd']);
51                 }
52             }
53         }
54         if (isset(
$args['url'])) {
55             
$url .= '&amp;' http_build_query($args['url'], '''&amp;');
56         }
57         if (!isset(
$args['width'])) {
58             
$args['width'] = $defaultWidth;
59         }
60         if (!isset(
$args['height'])) {
61             
$args['height'] = $defaultHeight;
62         }
63         
$args['params']['allowFullScreen'] =  'true';
64         
$html get::helper('html');
65         return 
$html->flash($url$args);
66     }
67
68     
/**
69      * Returns an AdSense ad
70      *
71      * Array args required: height, width
72      * Plus you need either: slot or channel
73      * And either 'client' or have the GOOGLE_AD_CLIENT constant set in your config
74      *
75      * @param array $args
76      * @return string
77      */
78     
public function adSense(array $args) {
79         if (!isset(
$args['client'])) {
80             
$args['client'] = get::$config->GOOGLE_AD_CLIENT;
81         }
82         foreach (
$args as $key => $val) {
83             if (
$val) {
84                 if (!
is_numeric($val)) {
85                     
$val '"' $val '"';
86                 }
87                 
$jsArgs[] = 'google_ad_' $key ' = ' $val ';';
88             }
89         }
90         if (isset(
$jsArgs)) {
91             
$adUrl 'http://pagead2.googlesyndication.com/pagead/show_ads.js';
92             
$html get::helper('html');
93             
$return $html->jsInline(implode(PHP_EOL$jsArgs)) . '<script type="text/javascript" src="' $adUrl
 
'"></script>';
94             return 
$return;
95         }
96     }
97
98     
/**
99      * Builds a link in the format used by the helper tools
100      *
101      * @param string $url
102      * @param string $data
103      * @param string $text
104      * @param array $args
105      * @return string
106      */
107     
protected function _link($url$data$text null, array $args = array()) {
108         if (
$text == null) {
109             
$text $data;
110         }
111         
$html get::helper('html');
112         return 
$html->link($url$text$args);
113     }
114
115     
/**
116      * Generate a link to Tweet on Twitter
117      *
118      * This has the same signature as $html->link() except that the 1st argument is your Tweet text instead of
 
link URL.
119      *
120      * 
Returns a tweet-linkAfter calling this method the Twitter Tweet URL can be accessed via:
 
$tools->twitterLink
121      
*
122      * @
param string $tweet
123      
* @param string $text
124      
* @param array $args
125      
* @return string
126      
*/
127     public function 
twitterLink($tweet$text null, array $args = array()) {
128         
$this->twitterLink 'http://twitter.com/home?status=' urlencode($tweet);
129         return 
$this->_link($this->twitterLink$tweet$text$args);
130     }
131
132     
/**
133      * Links to a location on Google Maps
134      *
135      * This has the same signature as $html->link() except that the first argument is your location instead of
 
link URL.
136      *
137      * 
Map URL can be accessed after utilizing this method via$tools->googleMapLink
138      
*
139      * @
param string $address
140      
* @param string $text
141      
* @param array $args
142      
* @return string
143      
*/
144     public function 
googleMapLink($address$text null, array $args = array()) {
145         
$this->googleMapLink 'http://maps.google.com/maps?sa=N&tab=nl&q=' urlencode($address);
146         return 
$this->_link($this->googleMapLink$address$text$args);
147     }
148
149     
/**
150      * Internal map counter
151      * @var int
152      */
153     
protected $_mapCount = -1;
154
155     
/**
156      * Escape text to be safely used as a JavaScript srting
157      *
158      * @param str $str
159      * @return str
160      */
161     
protected function _jsString($str) {
162         return 
addslashes(str_replace(array(PHP_EOL"\r""\n"), ', '$str));
163     }
164
165     
/**
166      * Generate a Google map
167      *
168      * Args keys are:
169      * mapType Options are: HYBRID (default), ROADMAP, SATELLITE, TERRAIN
170      * height, width
171      * zoom
172      * marker - marker used for your position on the map, takes an array of marker arguments (defined below)
173      * markers - array of additional positions on the map, can be array(location1, location2, ...)
174      *  or array(location1 => array('icon' => 'iconurl', ...), location2 => array('shadow' => 'shadowurl', ...),
 
...)
175      * 
options (array sent to the Google Map as args)
176      * 
dontAjax disable the AJAX load accelerator
177      
*
178      * 
Marker arguments are defined by the Google API at
179      
*  http://code.google.com/apis/maps/documentation/v3/reference.html#Marker plus an extra option of "info" to
180      
*  populate the popup baloon that opens when a marker is clicked
181      
*
182      * @
param str $location
183      
* @param array $args
184      
* @return str
185      
*/
186     public function 
googleMap($location, array $args = array()) {
187         
$html get::helper('html');
188         
$location $this->_jsString($location);
189         
$mapType 'HYBRID';
190         
$defaultDimension $height $width '250px';
191         
$zoom 15;
192         
extract($args);
193         if (!isset(
$options['zoom']) || !$options['zoom']) {
194             
$options['zoom'] = (int) $zoom;
195         }
196         if (
is_numeric($height)) {
197             
$height .= 'px';
198         } else if (
$height === null) {
199             
$height $defaultDimension;
200         }
201         if (
is_numeric($width)) {
202             
$width .= 'px';
203         } else if (
$width === null) {
204             
$width $defaultDimension;
205         }
206         
$return $js '';
207         if (!++
$this->_mapCount) {
208             
$jsUrl = (!isset($dontAjax) ?
 
'http://www.google.com/jsapi?autoload=%7Bmodules%3A%5B%7Bname%3A%22maps%22%2C'
209                                           
'version%3A3%2Cother_params%3A%22sensor%3Dfalse%22%7D%5D%7D'
210                                         
'http://maps.google.com/maps/api/js?sensor=false');
211             
$return $html->js($jsUrl);
212             
$js .= 'var geocoder, lastInfoWindow, firstLocation = {};
213 var codeAddress = function(map, address, thisMarkerArgs) {
214     if (!geocoder) {
215         return;
216     }
217     geocoder.geocode({"address": address}, function(results, status) {
218         if (status == google.maps.GeocoderStatus.OK) {
219             if (typeof firstLocation[map.getDiv().id] == "undefined") {
220                 map.setCenter(results[0].geometry.location);
221                 firstLocation[map.getDiv().id] = true;
222             }
223             var markerArgs = (typeof thisMarkerArgs == "undefined" ? {} : thisMarkerArgs);
224             markerArgs.map = map;
225             markerArgs.position = results[0].geometry.location;
226             var marker = new google.maps.Marker(markerArgs);
227             if (typeof thisMarkerArgs != "undefined" && typeof thisMarkerArgs.info != "undefined") {
228                 var infowindow = new google.maps.InfoWindow({content: thisMarkerArgs.info});
229                 google.maps.event.addListener(marker, "click", function() {
230                     if (typeof lastInfoWindow != "undefined") {
231                         lastInfoWindow.close();
232                     }
233                     infowindow.open(map, marker);
234                     lastInfoWindow = infowindow;
235                 });
236             }
237         } else if (status == google.maps.GeocoderStatus.ZERO_RESULTS
238                    || status == google.maps.GeocoderStatus.INVALID_REQUEST) {
239             map.zoom = 1;
240             codeAddress(map, "USA");
241         } else {
242             map.getDiv().innerHTML = status;
243         }
244     });
245 }' 
PHP_EOL;
246         }
247         
$js .= 'document.writeln("<div id=\"googlemap' $this->_mapCount '\"></div>");
248 var googlemapDiv' 
$this->_mapCount ' = document.getElementById("googlemap' $this->_mapCount '");
249 googlemapDiv' 
$this->_mapCount '.style.height = "' $height '";
250 googlemapDiv' 
$this->_mapCount '.style.width = "' $width '";
251 var googlemapObj' 
$this->_mapCount ';
252 var googlemap' 
$this->_mapCount ' = function() {
253     geocoder = new google.maps.Geocoder();
254     var args = ' 
json_encode($options) . ';
255     args.mapTypeId = google.maps.MapTypeId.' 
$mapType ';
256     googlemapObj' 
$this->_mapCount ' = new google.maps.Map(googlemapDiv' $this->_mapCount ', args);
257     codeAddress(googlemapObj' 
$this->_mapCount ', "' $location '"';
258             if (isset(
$marker)) {
259                 
$js .= ', ' json_encode($marker);
260             }
261             
$js .= ');' PHP_EOL;
262          if (isset(
$markers)) {
263              foreach (
$markers as $address => $thisMarker) {
264                 if (!
is_array($thisMarker)) {
265                     
$address $thisMarker;
266                 }
267                 
$js .= 'codeAddress(googlemapObj' $this->_mapCount ', "' $this->_jsString($address) . '"';
268                 if (
is_array($thisMarker)) {
269                     
$js .= ', ' json_encode($thisMarker);
270                 }
271                 
$js .= ');' PHP_EOL;
272             }
273         }
274         
$js .= '}' PHP_EOL;
275         if (!isset(
$dontAjax)) {
276             
$js .= 'google.setOnLoadCallback(googlemap' $this->_mapCount ');';
277         } else {
278             
$js .= 'window.onload=function() {';
279             for (
$x 0$x <= $this->_mapCount$x++) {
280                 
$js .= 'googlemap' $x '();';
281             }
282             
$js .= '};';
283         }
284         
$return .= $html->jsInline($js);
285         return 
$return;
286     }
287
288     
/**
289      * Languages currently supported by translation system
290      * @var array
291      */
292     
protected $_languages = array(
293         
'af' => 'Afrikaans''sq' => 'Albanian''ar' => 'Arabic''be' => 'Belarusian''bg' => 'Bulgarian',
294         
'ca' => 'Catalan''zh-CN' => 'Chinese (Simplified)''zh-TW' => 'Chinese (Traditional)''hr' =>
 
'Croatian',
295         
'cs' => 'Czech''da' => 'Danish''nl' => 'Dutch''en' => 'English''et' => 'Estonian''tl' =>
 
'Filipino',
296         
'fi' => 'Finnish''fr' => 'French''gl' => 'Galician''de' => 'German''el' => 'Greek''iw' =>
 
'Hebrew',
297         
'hi' => 'Hindi''hu' => 'Hungarian''is' => 'Icelandic''id' => 'Indonesian''ga' => 'Irish',
298         
'it' => 'Italian''ja' => 'Japanese''ko' => 'Korean''lv' => 'Latvian''lt' => 'Lithuanian',
299         
'mk' => 'Macedonian''ms' => 'Malay''mt' => 'Maltese''no' => 'Norwegian''fa' => 'Persian',
300         
'pl' => 'Polish''pt' => 'Portuguese''ro' => 'Romanian''ru' => 'Russian''sr' => 'Serbian',
301         
'sk' => 'Slovak''sl' => 'Slovenian''es' => 'Spanish''sw' => 'Swahili''sv' => 'Swedish',
302         
'th' => 'Thai''tr' => 'Turkish''uk' => 'Ukrainian''vi' => 'Vietnamese''cy' => 'Welsh''yi' =>
 
'Yiddish'
303     
);
304
305     
/**
306      * Read-only access to the languages property
307      * @return array
308      */
309     
public function languages() {
310         return 
$this->_languages;
311     }
312
313     
/**
314      * Generates a link to Google Translate. Languages supported are in the $_languages property
315      *
316      * @param str $to Language code to translate to
317      * @param str $url Optional, current page will be used if omitted
318      * @param str $from Optional Original language code of the page getting translated, omit for automatic
 
selection
319      
* @param str $headerLanguage Optionallanguage of the Google Header, if Google does not support the
320      
*                                      header language then it will use English in the header instead
321      
* @return str
322      
*/
323     public function 
googleTranslateUrl($to$url null$from null$headerLanguage null) {
324         if (!
$url) {
325             
$url 'http://' $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
326         }
327         
$url 'http://translate.google.com/translate?ie=UTF-8&u=' urlencode($url) . '&tl=' $to;
328         if (
$from) {
329             
$url .= '&sl=' $from;
330         }
331         if (
$headerLanguage) {
332             
$url .= '&hl=' $headerLanguage;
333         }
334         return 
$url;
335     }
336
337     
/**
338      * Flag if vork.translateById() JavaScript function has been returned
339      * @var Boolean
340      */
341     
protected $_googleLanguageLoaded false;
342
343     
/**
344      * Translate the innerHTML of an HTML container or the value of a form text input by its ID
345      *
346      * If all arguments are omitted then this method will only initialize the translate engine, you will need
347      * to call the translation function from the page via JavaScript: vork.translateById('id', 'to', 'from')
348      *
349      * @param str $to Language code (eg. es, ru, etc.)
350      * @param str $id ID of an HTML container or form text element
351      * @param str $from Optional language code, if omitted this will auto-detect
352      * @return str
353      */
354     
public function googleTranslateById($id null$to null$from '') {
355         
$html get::helper('html');
356         
$js = ($id == null '' 'google.setOnLoadCallback(function() {vork.translateById("'
357                                                                         
$id .'", "' $to .'", "' $from
 
.'")});');
358         if (!
$this->_googleLanguageLoaded) {
359             
$rtl = array('he''yi''ar''fa');
360             
$js $html->jsTools(true)
361                 . 
'vork.translateLastLang = {}' PHP_EOL
362                 
'vork.rtl = {"' implode('":1, "'$rtl) . '":1}' PHP_EOL
363                 
'vork.translateById = function(id, to, from) {' PHP_EOL
364                 
'    if (typeof from == "undefined") {' PHP_EOL
365                 
'        from = (typeof vork.translateLastLang[id] == "undefined" || vork.translateLastLang[id]
 == to
366                                    ? "en" : vork.translateLastLang[id]);' 
PHP_EOL
367                 
'    }' PHP_EOL
368                 
'    vork.translateLastLang[id] = to;' PHP_EOL
369                 
'    var domid = dom(id);' PHP_EOL
370                 
'    var textcontent = (domid.type == "textarea" || domid.type == "input"'
371                                       
' ? domid.value.replace(/\n/g, "<br />") : domid.innerHTML);' PHP_EOL
372                 
'    google.language.translate(textcontent, from, to, function(result) {' PHP_EOL
373                 
'        if (result.translation) {' PHP_EOL
374                 
'            if (domid.type == "textarea" || domid.type == "input") {' PHP_EOL
375                 
'                domid.value = result.translation.replace(/<br \/>/g, "\n");' PHP_EOL
376                 
'            } else {' PHP_EOL
377                 
'                domid.innerHTML = result.translation;' PHP_EOL
378                 
'            }' PHP_EOL
379                 
'            domid.style.direction = (typeof vork.rtl[to] == "undefined" ? "ltr" : "rtl");' .
 
PHP_EOL
380                 
'        }' PHP_EOL
381                 
'    });' PHP_EOL
382                 
'}' PHP_EOL $js;
383             
$this->_googleLanguageLoaded true;
384             
$return[] = $html->jsLoad('language');
385         }
386         
$return[] = $html->jsInline($js);
387         return 
implode($return);
388     }
389
390     
/**
391      * Builds a chart using Google Chart
392      * Documentation at: http://code.google.com/apis/chart/
393      *
394      * @param array $args
395      * @param array $imgArgs Passed to the $html->img() method directly
396      * @return str
397      */
398     
public function chart(array $args, array $imgArgs = array()) {
399         
$imgArgs['src'] = 'http://chart.apis.google.com/chart?' urldecode(http_build_query($args));
400         
$html get::helper('html');
401         return 
$html->img($imgArgs);
402     }
403
404     
/**
405      * Generates a QR code (the modern version of a UPC code) using Google Chart
406      *
407      * @param str $str
408      * @param array $args Optional, keys for size (in px), margin (in px), ecLevel (valid options are L, M, Q, H)
409      * @return str
410      */
411     
public function qrCode($str, array $args = array()) {
412         
//default is 2x size (plus margin) of typical QR version for the error correction level (L=V.2, M/Q=V.3,
 H=V.4)
413         
$ecCodes = array('L' => 58'M' => 66'Q' => 66'H' => 74);
414         if (isset(
$args['ecLevel'])) {
415             
$args['ecLevel'] = strtoupper($args['ecLevel']);
416         }
417         
$ecLevel = (isset($args['ecLevel']) && isset($ecCodes[$args['ecLevel']]) ? $args['ecLevel'] : 'L');
418         
$size = (isset($args['size']) ? (int) $args['size'] : $ecCodes[$ecLevel]);
419         
$margin = (isset($args['margin']) ? (int) $args['margin'] : 2); //half-the-minimum margin, since 2x the
 size
420         
$chartArgs = array('cht' => 'qr''choe' => 'UTF-8''chs' => $size 'x' $size'chl' =>
 
urlencode($str),
421                            
'chld' => $ecLevel '|' $margin);
422         return 
$this->chart($chartArgs);
423     }
424
425     
/**
426      * Creates an AddThis widget (requires setting your AddThis publisher code in the config or passing 'id'
 
argument)
427      *
428      * @
param array $args OptionalCan be any parameters defined in the AddThis API plus 'id'
429      
* @return string
430      
*/
431     public function 
addThis(array $args = array()) {
432         
$url = (isset($args['url']) ? $args['url'] : '[URL]');
433         
$title = (isset($args['title']) ? $args['title'] : '[TITLE]');
434         
$html get::helper('html');
435         
$id = (!isset($args['id']) ? get::$config->ADD_THIS $args['id']);
436         
$return '<a href="http://www.addthis.com/bookmark.php?v=250&amp;pub=' $id
437                 
'" onmouseover="return addthis_open(this, \'\', \'' $url '\', \'' $title
438                 
'\')" onmouseout="addthis_close()" onclick="return addthis_sendto()">'
439                 
$html->img(array('src' => 'http://s7.addthis.com/static/btn/lg-share-en.gif',
440                                    
'width' => 125'height' => 16'alt' => 'Bookmark and Share'))
441                 . 
'</a>' $html->js('http://s7.addthis.com/js/250/addthis_widget.js?pub=' $id);
442         if (
$args) {
443             foreach (
$args as $key => $val) {
444                 if (!
is_array($val)) {
445                     
$val "'" $val "'";
446                 } else {
447                     foreach (
$val as $k => $v) {
448                         
$valObj[] = $k ': "' $v '"';
449                     }
450                     
$val '{' implode(', '$valObj) . '}';
451                 }
452                 
$jsArgs[] = 'var ' $key '=' $val ';';
453             }
454             
$return $html->jsInline(implode(PHP_EOL$jsArgs)) . $return;
455         }
456         return 
$return;
457     }
458
459     
/**
460      * Creates a ShareThis widget (requires setting your ShareThis publisher code in the config or id argument)
461      *
462      * @param array $services Optional, a default set of services will be used if ommitted. Special "id" key is
463      *                        required if ShareThis publisher code is not set in the config
464      * @return string
465      */
466     
public function shareThis(array $services null) {
467         if (isset(
$services['id'])) {
468             
$id $services['id'];
469             unset(
$services['id']);
470         } else {
471             
$id get::$config->SHARE_THIS;
472         }
473         if (!
$services) {
474             
$services = array('twitter''linkedin''facebook''digg''ybuzz''stumbleupon''delicious',
475                               
'technorati''google_bmarks''myspace''windows_live''slashdot''blogger',
476                               
'wordpress''typepad''reddit''newsvine''mixx''fark''bus_exchange',
477                               
'propeller''livejournal''friendfeed''yahoo_bmarks');
478         }
479         
$html get::helper('html');
480         return 
$html->js('http://w.sharethis.com/button/sharethis.js#publisher=' $id
481                        
'&amp;type=website&amp;style=rotate&amp;post_services=' implode('%2C'$services));
482     }
483
484     
/**
485      * Generate an array of tag links
486      *
487      * @param array $tags Array key is the tag, value is the tag weight
488      * @param array $args Optional, keys are: baseUrl, (bool) standardDeviation
489      * @return array
490      */
491     
public function tagCloudTags(array $tags, array $args = array()) {
492         
$baseUrl = (isset($args['baseUrl']) ? $args['baseUrl'] : '');
493         
$tagsCopy $tags;
494         
asort($tagsCopySORT_NUMERIC);
495         
$tagCount count($tags);
496         
$standardDeviation = (!isset($args['standardDeviation']) ? ($tagCount 5) : (bool)
 
$args['standardDeviation']);
497         if (
$standardDeviation) { //apply standard deviation
498             
array_pop($tagsCopy);
499             
array_shift($tagsCopy);
500             
$min current($tagsCopy);
501             
$avg = (array_sum($tagsCopy) / ($tagCount 2));
502             
$increment = (($avg $min) / 4);
503         } else { 
//simple arithmetic
504             
$min current($tagsCopy);
505             
$max end($tagsCopy);
506             
$increment = (($max $min) / 9);
507         }
508         
$increment max($increment0.000001); //avoid division-by-zero issues
509         
$html get::helper('html');
510         foreach (
$tags as $tag => $val) {
511             
$return[] = $html->link($baseUrl $tag$tag, array('class' => 'cloud' max(min(floor($val /
 $increment), 9), 0)));
512         
}
513         return 
$return;
514     }
515
516     
/**
517      * Gets a tag cloud
518      *
519      * @param array $tags Array key is the tag, value is the tag weight
520      * @param array $args Optional, keys are: (bool) noCss, multiplier, baseUrl, (bool) standardDeviation
521      * @return str
522      */
523     
public function tagCloud(array $tags, array $args = array()) {
524         
$html get::helper('html');
525         if (!isset(
$args['noCss']) || !$args['noCss']) {
526             
$multiplier = (!isset($args['multiplier']) ? $args['multiplier']);
527             
$cssRange range(09);
528             
$increment 2;
529             foreach (
$cssRange as $level) {
530                 
$css[] = '.cloud' $level ' {font-size: ' . ((++$increment $level) * $multiplier) . '0%;}';
531             }
532             
$return[] = $html->cssInlineSingleton(implode(' '$css));
533         }
534         
$tags $this->tagCloudTags($tags$args);
535         
$return[] = '<div class="tagcloud">' implode(' '$tags) . '</div>';
536         return 
implode($return);
537     }
538
539     
/**
540      * Generates a 3D ball of your Flick feed (will only display for users with Flash installed)
541      * Uses Photo widget from www.roytanck.com modified to parse Flickr XML feeds
542      *
543      * @param str $feedId
544      * @param str $args
545      */
546     
public function flickrBall($feedId, array $args = array()) {
547         
$html get::helper('html');
548         
$flickrApi 'feed=http%3A//api.flickr.com/services/feeds/photos_public.gne'
549                    
'%3Flang%3Den-us%26format%3Drss_200%26id%3D' $feedId;
550         if (
substr($feedId, -42) != '@N') {
551             
$flickrApi .= '@N00';
552         }
553         
$bgcolor = (isset($args['bgcolor']) ? $args['bgcolor'] : '#ffffff');
554         
$params = array('AllowScriptAccess' => 'always''flashvars' => $flickrApi'bgcolor' => $bgcolor);
555         
$object = array('width' => (isset($args['width']) ? $args['width'] : 200),
556                         
'height' => (isset($args['height']) ? $args['height'] : 200));
557         
$args['params'] = (!isset($args['params']) ? $params array_merge($params$args['params']));
558         
$args['object'] = (!isset($args['object']) ? $object array_merge($object$args['object']));
559         return 
$html->flash('/assets/flickrball.swf'$args);
560     }
561
562     
/**
563      * Embed an MP3 player
564      * Valid $args keys: bgcolor, bgcolor2 (for gradient effect), height, width,
565      *                   (Booleans:) autoplay, loop, hidePlaylist
566      *                   FlashVars (direct entry to the FlashVars property, full features at
567      *                              http://flash-mp3-player.net/players/multi/generator/)
568      *
569      * @param mixed $mp3files Can be a string or an array of strings or key=>val pairs (mp3file => title)
570      * @param array $args
571      * @return str
572      */
573     
public function mp3Player($mp3files, array $args = array()) {
574         
$html get::helper('html');
575         if (!
is_array($mp3files)) {
576             
$mp3files = array($mp3files);
577         }
578         if (isset(
$mp3files[0])) {
579             foreach (
$mp3files as $key => $file) {
580                 if (!
$file) {
581                     unset(
$mp3files[$key]);
582                 }
583             }
584             
$vars[] = 'mp3=' urlencode(str_replace('\\''/'implode('|'$mp3files)));
585         } else {
586             foreach (
$mp3files as &$title) {
587                 
$title str_replace('|'''$title);
588             }
589             
$vars[] = 'title=' urlencode(implode('|'$mp3files));
590             
$vars[] = 'mp3=' urlencode(str_replace('\\''/'implode('|'array_keys($mp3files))));
591         }
592         
$height = (count($mp3files) === || (isset($args['hidePlaylist']) && $args['hidePlaylist']) ? 20 100);
593         if (
$height == 20) {
594             
$vars[] = 'showlist=0';
595         }
596         
$args['object']['height'] = (!isset($args['height']) ? $height : (int) $args['height']);
597         
$args['object']['width'] = (!isset($args['width']) ? 250 : (int) $args['width']);
598         
$vars[] = 'width=' $args['object']['width'];
599         
$vars[] = 'height=' $args['object']['height'];
600         if (isset(
$args['bgcolor'])) {
601             
$args['bgcolor'] = str_replace('#'''$args['bgcolor']);
602             
$vars[] = 'bgcolor1=' $args['bgcolor'];
603             
$vars[] = 'bgcolor2=' . (isset($args['bgcolor2']) ? str_replace('#'''$args['bgcolor2'])
604                                                               : 
$args['bgcolor']);
605         }
606         
$vars[] = 'autoplay=' . (!isset($args['autoplay']) ? : (int) (bool) $args['autoplay']);
607         
$vars[] = 'loop=' . (!isset($args['loop']) ? : (int) (bool) $args['loop']);
608         
$vars[] = 'showvolume=1';
609         
$vars[] = 'showinfo=' . (!isset($args['showinfo']) ? : (int) (bool) $args['showinfo']);
610         if (isset(
$args['FlashVars'])) {
611             
$vars[] = $args['FlashVars'];
612         }
613         
$args['params']['FlashVars'] = implode('&amp;'$vars);
614         return 
$html->flash('/assets/mp3player.swf'$args);
615     }
616
617     
/**
618      * Builds the URL to access the Meetup API
619      *
620      * @param string $service Must be a valid Meetup service as defined in their API (eg. groups, events, members,
 
etc.
621      * @
param array $args
622      
* @return string
623      
*/
624     protected function 
_getMeetupUrl($service, array $args) {
625         if (!isset(
$args['key'])) {
626             
$args['key'] = get::$config->MEETUP_API_KEY;
627         }
628         return 
'http://api.meetup.com/' $service '.json/?' http_build_query($args);
629     }
630
631     
/**
632      * Contains the last raw JSON string retrieved from the Meetup API
633      * @var string JSON
634      */
635     
public $meetup;
636
637     
/**
638      * Queries the Meetup API and returns the results in an array and saves the raw JSON data in $tools->meetup
639      *
640      * @param string $service
641      * @param array $args
642      * @return array
643      */
644     
public function meetup($service, array $args) {
645         
$this->meetup file_get_contents($this->_getMeetupUrl($service$args));
646         return 
json_decode(utf8_encode($this->meetup), true);
647     }
648
649     
/**
650      * Generates an array of html-valid ASCII codes for easy generation of HTML ascii or displaying an ASCII
 
table
651      
*
652      * @
param int $min Starting ASCII number
653      
* @param int $max Ending ASCII number
654      
* @return string
655      
*/
656     public function 
ascii($min 0$max 10000) {
657         
$range range($min$max);
658         return 
array_combine($range,
659                   
array_map(create_function('$val''return "&#" . str_pad($val, 4, 0, STR_PAD_LEFT) . ";";'),
 
$range));
660     }
661
662     
/**
663      * Returns the IP address of the user; automatically bypasses local-IPs of load-balancers
664      * @return string
665      */
666     
public function ip() {
667         if (isset(
$_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
668             
$ips explode(' '$_SERVER['HTTP_X_FORWARDED_FOR']);
669             
$ip array_pop($ips);
670         } else if (isset(
$_SERVER['REMOTE_ADDR'])) {
671             
$ip $_SERVER['REMOTE_ADDR'];
672         }
673         return (isset(
$ip) ? $ip null);
674     }
675
676     
/**
677      * Keeps legacy naming convention working. New applications can safely remove this method.
678      *
679      * @param string $name
680      * @param array $args
681      * @return mixed
682      * @deprecated This keeps deprecated method names working but usage should be phased out.
683      */
684     
public function __call($name, array $args) {
685         if (
substr($name03) == 'get') {
686             
$newName strtolower($name[3]) . substr($name4);
687             if (
method_exists($this$newName)) {
688                 return 
call_user_func_array(array($this$newName), $args);
689             }
690         }
691         
trigger_error('Call to undefined method ' __CLASS__ '::' $name '()'E_USER_ERROR);
692     }
693 }