/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 . '&hl=en&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 .= '&fmt=' . $format;
46 if ($format > 17) {
47 $defaultWidth = 854;
48 $defaultHeight = 505;
49 if ($format > 21) {
50 $url .= '&hd=' . (!isset($args['hd']) ? 1 : $args['hd']);
51 }
52 }
53 }
54 if (isset($args['url'])) {
55 $url .= '&' . http_build_query($args['url'], '', '&');
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-link. After 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 Optional, language 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 Optional. Can 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&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 . '&type=website&style=rotate&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($tagsCopy, SORT_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($increment, 0.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']) ? 2 : $args['multiplier']);
527 $cssRange = range(0, 9);
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, -4, 2) != '@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) === 1 || (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']) ? 0 : (int) (bool) $args['autoplay']);
607 $vars[] = 'loop=' . (!isset($args['loop']) ? 1 : (int) (bool) $args['loop']);
608 $vars[] = 'showvolume=1';
609 $vars[] = 'showinfo=' . (!isset($args['showinfo']) ? 1 : (int) (bool) $args['showinfo']);
610 if (isset($args['FlashVars'])) {
611 $vars[] = $args['FlashVars'];
612 }
613 $args['params']['FlashVars'] = implode('&', $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($name, 0, 3) == 'get') {
686 $newName = strtolower($name[3]) . substr($name, 4);
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 }