Difference between revisions of "FlickrSet Extension"

From ThePlaz.com

Jump to: navigation, search
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
I wanted to be able to embed [http;//flickr.com Flickr] sets and tags directly on my website.  I did some research and I found an extension from [http://shohei.yokoyama.ac/Shohei_YOKOYAMA Shohei YOKOYAMA] in July 2010.  I made some changes (see Letter to the Author" below) in a very hackish manner.  These changes met my needs, but were not very robust.  The original author has continued to update his original extension: [http://shohei.yokoyama.ac/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2/MediaWiki_Extension/FlickrSet/unstable/en].  That may be a better choice then my unstable version.
+
I wanted to be able to embed [http://flickr.com Flickr] sets and tags directly on my website.  I did some research and I found an extension from [http://shohei.yokoyama.ac/Shohei_YOKOYAMA Shohei YOKOYAMA] in July 2010.  I made some changes (see Letter to the Author" below) in a very hackish manner.  These changes met my needs, but were not very robust.  The original author has continued to update his original extension: [http://shohei.yokoyama.ac/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2/MediaWiki_Extension/FlickrSet/unstable/en].  That may be a better choice then my unstable version.
  
 +
==Usage==
 +
<source lang="html4strict">
 +
<flickrset>72157624462428350</flickrset>
 +
<flickrtag>wii</flickrtag>
 +
</source>
  
<pre>
+
==Example==
 
<flickrset>72157624462428350</flickrset>
 
<flickrset>72157624462428350</flickrset>
 
<flickrtag>wii</flickrtag>
 
<flickrtag>wii</flickrtag>
</pre>
+
 
 +
 
 +
==Original Version==
 +
*[http://www.mediawiki.org/wiki/Extension:FlickrSet MediaWiki Site]
 +
*[http://shohei.yokoyama.ac/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2/MediaWiki_Extension/FlickrSet/en Authors Site]
 +
 
 +
==Letter to author==
 +
{{Tan Message|This is the letter I wrote to the original author describing the changes I made.  Hopefully we can release a more extensible version, combining my modifications into the original code.}}
 +
I started off by making style modifications.  First of all, I like when my code wraps on webpages.  I know this adds space to pages, but it makes things much more readable.  I also like indenting code so that I can better see how it flows.  You may not like my style modifications. 
 +
 
 +
The Ext JS can be loaded from Google.  This can be faster in some circumstances.  I would ship it with this default, so that way if people want to change it they can, but they don’t have to.  Also, I think that it is fine to reference the same JS twice.  If it is repeat, than the browser ignores it I believe.  You may want to add the ignore calling the JS lib back in.
 +
 
 +
As you can see many of the changes were just to fit my own needs.  That means they are not the most extensible.
 +
 
 +
So I added a title bar which shows the name of the set.  This should be handy.  This is an example of something which is not properly extensible.  It should be turned into options.  I did not research it, but there must be a way to do it in the wiki tag (ie <pre><flickrset titlebar=”true”>798093798</flickrset></pre>)
 +
 
 +
I also quickly converted the code to support flickr tags.  However, I ran into trouble when the flickr sending code tried to sign a request containing the nsid I received from flickr.  It worked when I hardcoded my nsid.  The 2 lines looked identical, but there must be some sort of issue.  Because I only needed to show tags from my flickr account, I did not investigate further.  This is a place that can be improved for a public release.
 +
 
 +
I moved the <script> tags into the body of the code.  This way it is only called if a user opens a wiki page with a flickr set/tag.  I prefer that.  It will allow the first page the user sees to load faster and instead slows the first flickr set/tag page down slightly.
 +
 
 +
I added optional support for static Google maps. http://code.google.com/apis/maps/documentation/staticmaps These load much quicker (one image, not a ton of JS and a bunch of tiles) but at the cost of interactivity.  I think it is a nice option.
 +
 
 +
Also, I got rid of the <flickrsets2> tag.  I don’t see a need for it; perhaps a cache expiry attribute in the wiki code (see above; cacheuntil=”20101231”).
 +
 
 +
Oh I made the thumbnail dim immediately when you click on it.  This just seemed right to me.
 +
 
 +
So my todos:
 +
I think there should be a loading spinner after you click on a thumbnail
 +
I think the next/show js functions could be combined somehow (they seem similar)
 +
I want to make a google map that shows the position of all of the photos in the set/tag.  This is similar to my http://geoov.com concept.
 +
 
 +
But thank you so much for providing such a nice foundation.  It will hopefully provide a nice addition to my website.  Also, hopefully you will like the modifications I worked on all weekend. I understand if you don’t want to implement them.  I’m sorry that I took out features (flickrset2) and totally changed the style.  I know that gets contentious and makes it harder to integrate changes.  If you do use some of my changes, please link back to http://theplaz.com
 +
 
 +
 
 +
==Code==
 +
===Skin Header===
 +
(this can most likely go somewhere nice with mediawiki, like with a hook)
 +
<pre><script type="text/javascript">function html_decode(input) {return input.replace(/\&amp;/g,"&");}</script></pre>
 +
 
 +
===Extension File===
 +
<source lang="php">
 +
<?php
 +
# FlickrSet MediaWiki extension v.1
 +
#  Shohei Yokoyama (Shizuoka Univ. Japan) 2010.07
 +
#  Michael Plasmeier (http://theplaz.com) 2010.07
 +
#
 +
#-Set Image List and Viewer (with Slideshow and Google Maps)
 +
# Featuring a cache
 +
#  Wiki Tag:  <flickrset>photo-set-id</flickrset>
 +
#  Ex :
 +
#    Flickr-Set url: http://www.flickr.com/photos/abarth500/sets/72157624120056693/
 +
#    <flickrset>72157624120056693</flickrset>
 +
#-Tag Image List and Viewer (with Slideshow and Google Maps)
 +
# Featuring a cache
 +
# Right now only with a hardcoded user
 +
#  Wiki Tag:  <flickrtag>tag</flickrtag>
 +
#  Ex :
 +
#    Flickr url: http://www.flickr.com/photos/theplaz/tags/berlin/
 +
#    <flickrtag>berlin</flickrtag>
 +
#-Set Thumbnails and Link
 +
# Tag :
 +
#    <flickrsetthumbs>photo-set-id1,photo-set-id2|PageTitle|LinkText</flickrsetthumbs>
 +
#        *LinkText is optional
 +
# Ex :
 +
#    Flickr-Set url: http://www.flickr.com/photos/abarth500/sets/72157624120056693/
 +
#                    http://www.flickr.com/photos/abarth500/sets/72157624324034434/
 +
#    Link to:        http://shohei.yokoyama.ac/Gallary/Indidnapolis_Motor_Speedway
 +
#    Link text:      CLICK HERE to enter the Photo gallary of Indianapolis Motor Speedway
 +
#    <flickrsetthumbs>72157624120056693,72157624324034434|Gallary/Indidnapolis_Motor_Speedway|CLICK HERE to enter the Photo gallary of Indianapolis Motor Speedway</flickrsetthumbs>
 +
#
 +
# This code is licensed under the Creative Commons Attribution-ShareAlike 3.0 License
 +
# For more information or the latest version visit
 +
# http://shohei.yokoyama.ac/ƒ\ƒtƒgƒEƒFƒA/MediaWiki_Extension/FlickrSet/en
 +
# http://shohei.yokoyama.ac/ƒ\ƒtƒgƒEƒFƒA/MediaWiki_Extension/FlickrSet (Japanses)
 +
 
 +
/* TODO
 +
static maps of all points
 +
Loading status image
 +
Combine next/show js code
 +
*/
 +
 
 +
 
 +
require_once 'HTTP/Request2.php';
 +
 
 +
 
 +
// User Setting ------------------------------------------------------
 +
//  Flickr
 +
define("wfFLICKRSET_APIKYE", ""); //<----Change!
 +
define("wfFLICKRSET_SECRET", ""); //<--------------------Change!
 +
define("wfFLICKRSET_REST",  "http://api.flickr.com/services/rest/");
 +
 
 +
//  Google Maps V3 API
 +
define("wfFLICKRSET_GMAPURL",'http://maps.google.com/maps/api/js?sensor=false'); //url for full google maps api
 +
define("wfFLICKRSET_GMAPSTATICURL",'http://maps.google.com/maps/api/staticmap?sensor=false'); //url for static google maps API
 +
define("wfUSE_JS_GMAP", FALSE); //if false use only a static google map picture (loads page faster, but not interactive)
 +
 
 +
//  Ext core 3
 +
define("wfFLICKRSET_EXTPATH",'http://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core.js');
 +
//--------------------------------------------------------------------
 +
 
 +
define("wfFLICKRSET_WIDTH",  549);
 +
define("wfFLICKRSET_HEIGHT", 549);
 +
define("wfFLICKRSET_BACKGROUND", "http://farm5.static.flickr.com/4060/4482574753_af9cc46021_o.png");
 +
define("wfFLICKRSET_CACHE",dirname(__FILE__)."/cache/");
 +
 
 +
function wfFlickrSet_getSig($secret, $args){
 +
    ksort($args);
 +
    $s = "";
 +
    foreach($args as $k => $v){
 +
        $s .= $k . $v;
 +
    }
 +
    return md5($secret . $s);
 +
}
 +
 
 +
function wfFlickrSet_callFlickerService($args,$POST = false){
 +
$args['api_sig'] = wfFlickrSet_getSig(wfFLICKRSET_SECRET, $args);
 +
$Req = new HTTP_Request2();
 +
if($POST){
 +
$Req->setMethod(HTTP_Request2::METHOD_POST);
 +
$url = FLICKR_REST;
 +
$Req->addPostParameter($args);
 +
}else{
 +
$url = wfFLICKRSET_REST . "?" . http_build_query($args);
 +
}
 +
$Req->setUrl($url);
 +
$res = $Req->send();
 +
return simplexml_load_string($res->getBody());
 +
}
 +
 
 +
$wgExtensionFunctions[] = 'wfFlickrSet';
 +
$wgExtensionCredits['parserhook'][] = array(
 +
        'name' => 'FlickrSet',
 +
        'description' => 'Display Flickr image sets and tags. Slideshow and Geotag are available.',
 +
        'author' => 'Shohei Yokoyama and Michael Plasmeier',
 +
        'url' => 'http://shohei.yokoyama.ac/'
 +
);
 +
 
 +
function wfFlickrSet() {
 +
        global $wgParser;
 +
        $wgParser->setHook('flickrset', 'renderFlickrSet');
 +
$wgParser->setHook('flickrtag', 'renderFlickrTag');
 +
$wgParser->setHook('flickrsetbanner', 'renderFlickrSetThumbs');
 +
$wgParser->setHook('flickrsetthumbs', 'renderFlickrSetThumbs');//old
 +
}
 +
 
 +
function renderFlickrSetThumbs($input,$arg,&$parser){
 +
$in = explode("|",$input);
 +
if(count($in)>=2){
 +
$page = $in[1];
 +
$inputs = explode(",",$in[0]);
 +
foreach($inputs as $i){
 +
if(!is_numeric($i)){
 +
return "<strong class='error'>PHOTO-ID ERROR</strong>";
 +
}
 +
}
 +
$input = str_replace(",","-",$in[0]);
 +
}else{
 +
return "<strong class='error'>INPUT ERROR</strong>";
 +
}
 +
if(count($in)>=3){
 +
$linkStr = $in[2];
 +
}else{
 +
$linkStr = "CLICK HERE to enter the photo gallery of '''".$page."'''";
 +
}
 +
$pagelink = $parser->recursiveTagParse("[[".$page."|".$linkStr."]]");
 +
$oldfile = wfFLICKRSET_CACHE."t+".ltrim($input,"+-");
 +
$newfile = wfFLICKRSET_CACHE."t-".ltrim($input,"+-");
 +
if(!strncmp($input,"-",1)){
 +
$f = $newfile;
 +
$newfile = $oldfile;
 +
$oldfile = $f;
 +
}
 +
if(is_file($oldfile)){
 +
unlink($oldfile);
 +
}
 +
if(is_file($newfile)){
 +
$output1 = file_get_contents($newfile);
 +
}else{
 +
$imgs=array();$q = 0;
 +
foreach($inputs as $setid){
 +
$photoset = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photosets.getPhotos',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'photoset_id' => $setid,
 +
'extras' => "url_sq",
 +
'per_page' => 30,
 +
'page' => 1,
 +
'media' => 'photos'
 +
));
 +
if((string)$photoset["stat"]!="fail"){
 +
$imgs[$q]=array();
 +
foreach($photoset->photoset->photo as $photo){
 +
$url = (string)$photo["url_sq"];
 +
array_push($imgs[$q],'<img src="'.$url.'"/>');
 +
}
 +
}else{
 +
$output = "<strong class='error'>FLICKR API ERROR (photoset ID)</strong>";
 +
return $output;
 +
}
 +
$q++;
 +
}
 +
$thumbs = array();
 +
$cc = 0;
 +
while(count($thumbs) < 30){
 +
for($c = 0; $c < $q; $c++){
 +
if(count($imgs[$c])>0){
 +
array_push($thumbs,array_shift($imgs[$c]));
 +
if(count($thumbs) >= 30){break;}
 +
}
 +
}
 +
if(count($thumbs) == $cc){
 +
break;
 +
}else{
 +
$cc = count($thumbs);
 +
}
 +
}
 +
$output1 = '<div id="_THUMB_'.$input.'" style="width:'.(count($thumbs)*75).'px;">'.implode("",$thumbs).'</div>';
 +
}
 +
$output = "";
 +
$output2 = "";
 +
$output0 = "";
 +
$output0 = '<div style="position:relative;height:79px;margin:0px 20px 20px 20px;padding:0px;background-color:#000;">
 +
<div id="_TLIST_'.$input.'" style="position:relative;top:0px;left:0px;height:75px;padding:2px 1px 2px 1px;background-color:#000;overflow:hidden;">';
 +
//$output1 here
 +
$output2 .= '</div>
 +
<div style="position:absolute;top:0px;left:0px;"><span style="background-color:#fff;padding:3px 5px 1px 5px;">'.$pagelink.'</span></div>
 +
</div>
 +
<script type="text/javascript">
 +
Ext.onReady(function(){
 +
Ext.get("_TLIST_'.$input.'").on("mousemove",function(e){
 +
var d = (e.getPageX()-Ext.get("_TLIST_'.$input.'").getX())/Ext.get("_TLIST_'.$input.'").getWidth();
 +
var w = Ext.get("_THUMB_'.$input.'").getWidth() - Ext.get("_TLIST_'.$input.'").getWidth();
 +
Ext.get("_THUMB_'.$input.'").setX(Ext.get("_TLIST_'.$input.'").getX()-Math.ceil(d*w),true);
 +
},this);
 +
},this);
 +
</script>';
 +
if(FALSE === file_put_contents($newfile,$output1) or $output1 == ""){
 +
$output = "<strong class='error'>Cache File ".$newfile." ERROR</strong>";
 +
return $output;
 +
}
 +
return $output0.$output1.$output2;
 +
}
 +
 
 +
 
 +
function renderFlickrSet($input) {
 +
if ( !is_numeric($input)) {
 +
$output = "<strong class='error'>Flickr Error ( Not a valid ID ): PhotoID ".htmlentities($input, ENT_QUOTES,mb_internal_encoding())." is not numeric</strong>";
 +
return $output;
 +
}
 +
$oldfile = wfFLICKRSET_CACHE."f+".ltrim($input,"+-");
 +
$newfile = wfFLICKRSET_CACHE."f-".ltrim($input,"+-");
 +
//theplaz 2010-7-17: if cache off or purge is in the url, bypass cache
 +
global $wgCachePages;
 +
//var_dump($wgCachePages);
 +
if ($wgCachePages != FALSE && $_GET["action"] != 'purge') {
 +
//echo 'checking cache';
 +
if(intval($input) > 0){
 +
$f = $newfile;
 +
$newfile = $oldfile;
 +
$oldfile = $f;
 +
}
 +
if(is_file($oldfile)){
 +
unlink($oldfile);
 +
}
 +
if(is_file($newfile)){
 +
//echo 'from cache';
 +
return file_get_contents($newfile);
 +
}
 +
}
 +
//echo 'new';
 +
$input = ltrim($input,"+-");
 +
$photoset_info = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photosets.getInfo',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'photoset_id' => $input
 +
));
 +
$photoset = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photosets.getPhotos',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'photoset_id' => $input,
 +
'extras' => "url_sq,url_m",
 +
'per_page' => 500,
 +
'page' => 1,
 +
'media' => 'photos'
 +
));
 +
if((string)$photoset["stat"]!="fail"){
 +
//added theplaz 2010-07-17 Title of flickr item
 +
$title = '<h3><a href="http://flickr.com"><strong><span style="color:#0063DC">flick</span><span style="color:#EE007B">r</span></strong></a> > <a href="http://flickr.com/photos/'.$photoset->photoset["ownername"].'/sets">'.$photoset->photoset["ownername"].'</a> > <a href="http://www.flickr.com/photos/theplaz/sets/'.$input.'/">'.$photoset_info->photoset->title.' <span style="font-size:12px">Set</span></a></h3>';
 +
return flickr_common_print($photoset->photoset, $input, $oldfile, $newfile, $title);
 +
}else{
 +
$output = "<strong class='error'>FlickrSets: photoset ID not numeric</strong>";
 +
return $output;
 +
}
 +
}
 +
//input format: user:tag
 +
//ie theplaz:berlin
 +
function renderFlickrTag($input) {
 +
//user was not working, just use mine static
 +
$user = 'theplaz';
 +
$tag = $input;
 +
 
 +
 
 +
$oldfile = wfFLICKRSET_CACHE."f+".ltrim($input,"+-");
 +
$newfile = wfFLICKRSET_CACHE."f-".ltrim($input,"+-");
 +
//theplaz 2010-7-17: if cache off or purge is in the url, bypass cache
 +
global $wgCachePages;
 +
//var_dump($wgCachePages);
 +
if ($wgCachePages != FALSE && $_GET["action"] != 'purge') {
 +
//echo 'checking cache';
 +
if(intval($input) > 0){
 +
$f = $newfile;
 +
$newfile = $oldfile;
 +
$oldfile = $f;
 +
}
 +
if(is_file($oldfile)){
 +
unlink($oldfile);
 +
}
 +
if(is_file($newfile)){
 +
//echo 'from cache';
 +
return file_get_contents($newfile);
 +
}
 +
}
 +
//echo 'new';
 +
$input = ltrim($input,"+-");
 +
/*$user_info = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.people.findByUsername',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'username' => $user
 +
));
 +
$nsid = $user_info->user['id'];
 +
echo $nsid;
 +
$photoset = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photos.search',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'user_id' => $nsid,
 +
'tags' => $tag,
 +
'per_page' => 500,
 +
'page' => 1,
 +
'media' => 'photos'
 +
));*/
 +
$photoset = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photos.search',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'user_id' => '77179348@N00',
 +
'extras' => "url_sq,url_m",
 +
'tags' => $tag,
 +
'per_page' => 500,
 +
'page' => 1,
 +
'media' => 'photos'
 +
));
 +
if((string)$photoset["stat"]!="fail"){
 +
//added theplaz 2010-07-17 Title of flickr item
 +
$title = '<h3><a href="http://flickr.com"><strong><span style="color:#0063DC">flick</span><span style="color:#EE007B">r</span></strong></a> > <a href="http://flickr.com/photos/'.$user.'/sets">'.$user.'</a> > <a href="http://www.flickr.com/photos/'.$user.'/tags/">tags</a> > <a href="http://www.flickr.com/photos/'.$user.'/tags/'.$tag.'/">'.$tag.'</a></h3>';
 +
return flickr_common_print($photoset->photos, $input, $oldfile, $newfile, $title);
 +
}else{
 +
$output = "<strong class='error'>FlickrSets: photoset ID not numeric</strong>";
 +
return $output;
 +
}
 +
}
 +
 
 +
function flickr_common_print($photos, $input, $oldfile, $newfile, $title) {
 +
$output2 = '';
 +
$output3 = '';
 +
$output2 = $title;
 +
 +
//print all of the JS needed to run this
 +
if (wfUSE_JS_GMAP) {
 +
$output = '<script type="text/javascript" src="'.wfFLICKRSET_GMAPURL.'"></script>';
 +
}
 +
$output = '<script type="text/javascript" src="'.wfFLICKRSET_EXTPATH.'"></script>
 +
<script type="text/javascript">
 +
var jsFLICKRSET_sel_'.$input.' = 0;
 +
var jsFLICKRSET_swap_'.$input.' = true;
 +
var jsFLICKRSET_runner_'.$input.' = new Ext.util.TaskRunner();
 +
var jsFLICKRSET_task_'.$input.' = {run:function(){
 +
jsFLICKRSET_next_'.$input.'();
 +
},scope:this,interval:5000};
 +
var jsFLICKRSET_started_'.$input.' = false;
 +
var jsFLICKRSET_mapped_'.$input.' = false;
 +
var jsFLICKRSET_STATIC_GMAP_ROOT'.$input.' = "'.wfFLICKRSET_GMAPSTATICURL.'";
 +
';
 +
// FUNCTION showmap ------------------------------------------------------------
 +
$output .= 'function jsFLICKRSET_showmap_'.$input.'(){
 +
if(jsFLICKRSET_mapped_'.$input.'){ //close
 +
var top = Ext.get("_BASE'.$input.'").getTop() - '.wfFLICKRSET_HEIGHT.';
 +
Ext.get("_MAP'.$input.'").setY(top,true);
 +
Ext.getDom("_SHOWMAPa'.$input.'").style.color="#aaaaaa";
 +
}else{ //open
 +
var top = Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2);
 +
Ext.get("_MAP'.$input.'").setY(top,true);
 +
Ext.getDom("_SHOWMAPa'.$input.'").style.color="#ff8888";
 +
}
 +
jsFLICKRSET_mapped_'.$input.'=!jsFLICKRSET_mapped_'.$input.'; //flip the bit
 +
}
 +
';
 +
// FUNCTION slideshow ------------------------------------------------------------
 +
$output.= 'function jsFLICKRSET_slideshow_'.$input.'(){
 +
if(jsFLICKRSET_started_'.$input.'){
 +
jsFLICKRSET_runner_'.$input.'.stop(jsFLICKRSET_task_'.$input.');
 +
Ext.getDom("_SLIDESHOW'.$input.'").style.color="#aaaaaa";
 +
}else{
 +
jsFLICKRSET_runner_'.$input.'.start(jsFLICKRSET_task_'.$input.');
 +
Ext.getDom("_SLIDESHOW'.$input.'").style.color="#ff8888";
 +
}
 +
jsFLICKRSET_started_'.$input.'=!jsFLICKRSET_started_'.$input.';
 +
}
 +
';
 +
// FUNCTION next ------------------------------------------------------------
 +
$output.= 'function jsFLICKRSET_next_'.$input.'(){
 +
var imgidnew = "_'.$input.'_A";
 +
var imgidold = "_'.$input.'_B";
 +
if(jsFLICKRSET_swap_'.$input.'){
 +
imgidnew="_'.$input.'_B";
 +
imgidold="_'.$input.'_A";
 +
}
 +
jsFLICKRSET_swap_'.$input.'=!jsFLICKRSET_swap_'.$input.';
 +
var info = jsFLICKRSET_info_'.$input.'(jsFLICKRSET_sel_'.$input.');
 +
Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setStyle("border-color","#fff");
 +
Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setOpacity(0.3,true);
 +
jsFLICKRSET_sel_'.$input.'++;
 +
if(jsFLICKRSET_sel_'.$input.'>=jsFLICKRSET_num_'.$input.'){
 +
jsFLICKRSET_sel_'.$input.'=0;
 +
}
 +
Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setStyle("border-color","#ff0000");
 +
info = jsFLICKRSET_info_'.$input.'(jsFLICKRSET_sel_'.$input.');
 +
var left = Ext.get("_BASE'.$input.'").getLeft() + Math.floor(('.wfFLICKRSET_WIDTH.'-info["width"])/2);
 +
var top = Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-info["height"])/2);';
 +
if (wfUSE_JS_GMAP) {
 +
$output .= 'if(info["geo"]){
 +
map'.$input.'.setCenter(new google.maps.LatLng(info["latitude"],info["longitude"]));
 +
marker'.$input.'.setPosition(new google.maps.LatLng(info["latitude"],info["longitude"]));
 +
if(jsFLICKRSET_mapped_'.$input.'){
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
 +
}
 +
}else{
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
 +
}';
 +
} else {
 +
$output .= 'if(info["geo"]){
 +
static_map_url = "&zoom=13&size=500x500&markers=size:mid|"+info["latitude"]+","+info["longitude"];
 +
Ext.get("_STATIC_MAP'.$input.'").set({src:  "'.wfFLICKRSET_GMAPSTATICURL.'"+html_decode(static_map_url)});
 +
if(jsFLICKRSET_mapped_'.$input.') {//if map is open
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
 +
}
 +
}else{
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
 +
}';
 +
}
 +
$output .= 'Ext.getDom("_'.$input.'_title").innerHTML = info["title"];
 +
Ext.getDom("_'.$input.'_description").innerHTML = info["description"];
 +
Ext.getDom("_'.$input.'_description").style.visibility = (info["description"]=="")?"hidden":"visible";
 +
Ext.getDom("_SHOWMAP'.$input.'").style.visibility = (info["geo"])?"visible":"hidden";
 +
Ext.get(imgidnew).setXY([left + '.wfFLICKRSET_WIDTH.',top]);
 +
Ext.get(imgidnew).setOpacity(1,true);
 +
Ext.get(imgidnew).setXY([left,top],true);
 +
Ext.get(imgidold).setOpacity(0,{callback:function(){
 +
var info = jsFLICKRSET_info_'.$input.'(1+jsFLICKRSET_sel_'.$input.');Ext.getDom(imgidold).src=info["url"];},scope:this});
 +
}
 +
';
 +
// FUNCTION show ------------------------------------------------------------
 +
$output.= 'function jsFLICKRSET_show_'.$input.'(id,url){
 +
var imgidnew = "_'.$input.'_A";var imgidold = "_'.$input.'_B";
 +
if(jsFLICKRSET_swap_'.$input.'){
 +
imgidnew="_'.$input.'_B";
 +
imgidold="_'.$input.'_A";
 +
}
 +
Ext.getDom(imgidold).src = url;
 +
Ext.get("_'.$input.'_"+id).setStyle("border-color","#ff0000");
 +
Ext.get("_'.$input.'_"+id).setOpacity(0.3,true);
 +
Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setStyle("border-color","#fff");
 +
Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setOpacity(0.3,true);
 +
var info = jsFLICKRSET_info_'.$input.'(id);
 +
var left = Ext.get("_BASE'.$input.'").getLeft() + Math.floor(('.wfFLICKRSET_WIDTH.'-info["width"])/2);
 +
var top = Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-info["height"])/2);';
 +
if (wfUSE_JS_GMAP) {
 +
$output .= 'if(info["geo"]){
 +
map'.$input.'.setCenter(new google.maps.LatLng(info["latitude"],info["longitude"]));
 +
marker'.$input.'.setPosition(new google.maps.LatLng(info["latitude"],info["longitude"]));
 +
if(jsFLICKRSET_mapped_'.$input.'){
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
 +
}
 +
}else{
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
 +
}';
 +
} else {
 +
$output .= 'if(info["geo"]){
 +
static_map_url = "&zoom=13&size=500x500&markers=size:mid|"+info["latitude"]+","+info["longitude"];
 +
Ext.get("_STATIC_MAP'.$input.'").set({src:  "'.wfFLICKRSET_GMAPSTATICURL.'"+html_decode(static_map_url)});
 +
if(jsFLICKRSET_mapped_'.$input.') {
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
 +
}
 +
}else{
 +
Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
 +
}';
 +
}
 +
$output .= 'Ext.getDom("_'.$input.'_title").innerHTML = info["title"];
 +
Ext.getDom("_'.$input.'_description").innerHTML = info["description"];
 +
Ext.getDom("_'.$input.'_description").style.visibility = (info["description"]=="")?"hidden":"visible";
 +
Ext.getDom("_SHOWMAP'.$input.'").style.visibility = (info["geo"])?"visible":"hidden";
 +
Ext.get(imgidold).setXY([left,top],true);
 +
info = jsFLICKRSET_info_'.$input.'(id+1);
 +
Ext.getDom(imgidnew).src = info["url"];
 +
jsFLICKRSET_sel_'.$input.' = id;
 +
}
 +
function jsFLICKRSET_info_'.$input.'(id){switch(id){';
 +
$c = 0;
 +
$lat=37.4419;$lon=-122.1419;
 +
$LAT=37.4419;$LON=-122.1419;
 +
foreach($photos->photo as $photo){
 +
$photoinfo = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photos.getInfo',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'photo_id' => (string)$photo["id"]
 +
));
 +
$phototitle = htmlentities((string)$photoinfo->photo->title, ENT_QUOTES,mb_internal_encoding());
 +
$photodescription = htmlentities((string)$photoinfo->photo->description, ENT_QUOTES,mb_internal_encoding());
 +
$photosizes = wfFlickrSet_callFlickerService(array(
 +
'method'  => 'flickr.photos.getSizes',
 +
'api_key' => wfFLICKRSET_APIKYE,
 +
'photo_id' => (string)$photo["id"]
 +
));
 +
$url = (string)$photo["url_m"];
 +
$width = 500;
 +
$height = 500;
 +
if((string)$photosizes["stat"]!="fail"){
 +
foreach($photosizes->sizes->size as $size){
 +
$url = $size["source"];
 +
$width = $size["width"];
 +
$height = $size["height"];
 +
if((string)$size["label"] == "Medium"){
 +
break;
 +
}
 +
}
 +
}
 +
$geo = "false";
 +
$visGeo = "hidden";
 +
if(isset($photoinfo->photo->location)){
 +
$geo = "true,'latitude':".(string)$photoinfo->photo->location["latitude"].",'longitude':".(string)$photoinfo->photo->location["longitude"];
 +
$lat = floatval((string)$photoinfo->photo->location["latitude"]);
 +
$lon = floatval((string)$photoinfo->photo->location["longitude"]);
 +
$visGeo = "visible";
 +
}
 +
$output  .= 'case '.$c.':return {"url":"'.$url.'","title":"'.htmlentities($phototitle).'","description":"'.htmlentities(nl2brr($photodescription)).'","width":'.$width.',"height":'.$height.',"geo":'.$geo.'};
 +
';
 +
$col = "#fff";
 +
if($c == 0){
 +
$LAT = $lat;
 +
$LON = $lon;
 +
$col ="#f00";
 +
$output2 .= '<div id="_BASE'.$input.'" style="position:relative;top:0px;left:0px;overflow:hidden;width:'.wfFLICKRSET_WIDTH.'px;height:'.wfFLICKRSET_WIDTH.'px;background-color:#000;border: 1px solid #ffffff;margin:1px;float:left;">
 +
<div id="_'.$input.'_title" style="z-index:105;position:absolute;top:0px;left:0px;color:#fff;font-weight:bold;font-size:large;padding:5px;">'.$phototitle.'</div>
 +
';
 +
$visDescription = "hidden";
 +
if($photodescription!=""){
 +
$visDescription = "visible";
 +
}
 +
$output2 .= '<div style="background-color:#00f;position:absolute;z-index:103;width:500px;height:500px;top:-'.(wfFLICKRSET_HEIGHT+10).'px;left:'.floor((wfFLICKRSET_WIDTH-500)/2).'px;"><div style="width:500px;height:500px;" id="_MAP'.$input.'">';
 +
if (!wfUSE_JS_GMAP) {
 +
$output2 .= '<img id="_STATIC_MAP'.$input.'" src="" />';
 +
}
 +
$output2 .= '</div></div><div id="_'.$input.'_description" style="visibility:'.$visDescription.';border:1px dotted #fff;z-index:104;background-image:url('.wfFLICKRSET_BACKGROUND.');position:absolute;top:0px;width:'.(wfFLICKRSET_WIDTH-120).'px;margin:55px 50px 0px 50px;left:0px;padding:5px 10px 5px 10px;text-justify:inter-ideograph;color:#fff;">'.$photodescription.'</div>
 +
<div style="z-index:102;color:#aaa;position:absolute;top:0px;left:'.(wfFLICKRSET_WIDTH-65).'px;">'."[<a id=\"_SLIDESHOW".$input."\" href=\"#\" onclick=\"jsFLICKRSET_slideshow_".$input."();return false;\" style=\"color:#aaa;\">Slideshow</a>]".'</div>
 +
<div id="_SHOWMAP'.$input.'" style="visibility:'.$visGeo.';z-index:101;color:#aaa;position:absolute;top:0px;left:'.(wfFLICKRSET_WIDTH-100).'px;">'."[<a id=\"_SHOWMAPa".$input."\" style=\"color:#aaa;\" href=\"#\" onclick=\"jsFLICKRSET_showmap_".$input."();return false;\" style=\"color:#aaa;\">Map</a>]".'</div>
 +
<img onclick="jsFLICKRSET_next_'.$input.'();" style="z-index:100;position:absolute;left:'.floor((wfFLICKRSET_WIDTH-$width)/2).'px;top:'.floor((wfFLICKRSET_HEIGHT-$height)/2).'px;" id="_'.$input.'_A" src="'.(string)$photo["url_m"].'"/>';
 +
}
 +
if($c == 1){
 +
$output2 .= '<img onclick="jsFLICKRSET_next_'.$input.'();" style="z-index:99;position:absolute;left:'.(wfFLICKRSET_WIDTH*2).'px;top:'.floor((wfFLICKRSET_HEIGHT-$height)/2).'px;" id="_'.$input.'_B" src="'.(string)$photo["url_m"].'"/>
 +
</div>';
 +
}
 +
$id = '_'.$input.'_'.$c;
 +
$output3 .= '<img style="border: 1px solid '.$col.';margin:1px" onclick="jsFLICKRSET_show_'.$input.'('.$c.',\''.(string)$photo["url_m"].'\');" id="'.$id.'" style="margin:1px;" src="'.(string)$photo["url_sq"].'"/>';
 +
$c++;
 +
}
 +
$output  .= 'default:return jsFLICKRSET_info_'.$input.'(0);}}
 +
            var jsFLICKRSET_num_'.$input.' = '.$c.';';
 +
if (wfUSE_JS_GMAP) {
 +
$output .= 'Ext.onReady(function(){
 +
map'.$input.' = new google.maps.Map(document.getElementById("_MAP'.$input.'"), {
 +
zoom:13,center:new google.maps.LatLng('.$LAT.','.$LON.'),
 +
mapTypeId:google.maps.MapTypeId.ROADMAP,
 +
mapTypeControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT,style:google.maps.MapTypeControlStyle.DROPDOWN_MENU},
 +
navigationControlOptions:{position:google.maps.ControlPosition.TOP_LEFT,style:google.maps.NavigationControlStyle.SMALL}
 +
});
 +
marker'.$input.' = new google.maps.Marker({clickable:false,position:new google.maps.LatLng('.$LAT.','.$LON.'),map:map'.$input.'});
 +
},this);';
 +
} else {
 +
//init with first img info
 +
$output .= 'static_map_url = "&zoom=13&size=500x500&markers=size:mid|'.$LAT.','.$LON.'";
 +
Ext.onReady(function(){
 +
Ext.get("_STATIC_MAP'.$input.'").set({src:  "'.wfFLICKRSET_GMAPSTATICURL.'"+html_decode(static_map_url)});
 +
});
 +
';
 +
}
 +
$output .= '</script>
 +
<p>';
 +
$output3 .= "<br clear='all'>";
 +
if(FALSE === file_put_contents($newfile,$output.$output2.$output3)){
 +
$output = "<strong class='error'>FlickrSets: Error writing cache file: ".$newfile."</strong>";
 +
return $output.$output2.$output3;
 +
}
 +
return $output.$output2.$output3;
 +
 +
}
 +
 
 +
function nl2brr($text)
 +
{
 +
    return preg_replace("/\r\n|\n|\r/", "<br>", $text);
 +
}
 +
 
 +
?>
 +
</source>
 +
 
 +
[[Category:Tech]]
 +
[[Category:MediaWiki]]
 +
[[Category:MediaWiki Extensions]]

Latest revision as of 04:58, 25 July 2012

I wanted to be able to embed Flickr sets and tags directly on my website. I did some research and I found an extension from Shohei YOKOYAMA in July 2010. I made some changes (see Letter to the Author" below) in a very hackish manner. These changes met my needs, but were not very robust. The original author has continued to update his original extension: [1]. That may be a better choice then my unstable version.

Contents

Usage

<flickrset>72157624462428350</flickrset>
<flickrtag>wii</flickrtag>

Example

flickr > theplaz > Second Day in Berlin Set

100_2820
[Map]


flickr > theplaz > tags > wii

P1040340



Original Version

Letter to author

This is the letter I wrote to the original author describing the changes I made. Hopefully we can release a more extensible version, combining my modifications into the original code.

I started off by making style modifications. First of all, I like when my code wraps on webpages. I know this adds space to pages, but it makes things much more readable. I also like indenting code so that I can better see how it flows. You may not like my style modifications.

The Ext JS can be loaded from Google. This can be faster in some circumstances. I would ship it with this default, so that way if people want to change it they can, but they don’t have to. Also, I think that it is fine to reference the same JS twice. If it is repeat, than the browser ignores it I believe. You may want to add the ignore calling the JS lib back in.

As you can see many of the changes were just to fit my own needs. That means they are not the most extensible.

So I added a title bar which shows the name of the set. This should be handy. This is an example of something which is not properly extensible. It should be turned into options. I did not research it, but there must be a way to do it in the wiki tag (ie
<flickrset titlebar=”true”>798093798</flickrset>
)

I also quickly converted the code to support flickr tags. However, I ran into trouble when the flickr sending code tried to sign a request containing the nsid I received from flickr. It worked when I hardcoded my nsid. The 2 lines looked identical, but there must be some sort of issue. Because I only needed to show tags from my flickr account, I did not investigate further. This is a place that can be improved for a public release.

I moved the <script> tags into the body of the code. This way it is only called if a user opens a wiki page with a flickr set/tag. I prefer that. It will allow the first page the user sees to load faster and instead slows the first flickr set/tag page down slightly.

I added optional support for static Google maps. http://code.google.com/apis/maps/documentation/staticmaps These load much quicker (one image, not a ton of JS and a bunch of tiles) but at the cost of interactivity. I think it is a nice option.

Also, I got rid of the <flickrsets2> tag. I don’t see a need for it; perhaps a cache expiry attribute in the wiki code (see above; cacheuntil=”20101231”).

Oh I made the thumbnail dim immediately when you click on it. This just seemed right to me.

So my todos: I think there should be a loading spinner after you click on a thumbnail I think the next/show js functions could be combined somehow (they seem similar) I want to make a google map that shows the position of all of the photos in the set/tag. This is similar to my http://geoov.com concept.

But thank you so much for providing such a nice foundation. It will hopefully provide a nice addition to my website. Also, hopefully you will like the modifications I worked on all weekend. I understand if you don’t want to implement them. I’m sorry that I took out features (flickrset2) and totally changed the style. I know that gets contentious and makes it harder to integrate changes. If you do use some of my changes, please link back to http://theplaz.com


Code

Skin Header

(this can most likely go somewhere nice with mediawiki, like with a hook)

<script type="text/javascript">function html_decode(input) {return input.replace(/\&/g,"&");}</script>

Extension File

<?php
# FlickrSet MediaWiki extension v.1
#   Shohei Yokoyama (Shizuoka Univ. Japan) 2010.07
#   Michael Plasmeier (http://theplaz.com) 2010.07
# 
#-Set Image List and Viewer (with Slideshow and Google Maps)
# Featuring a cache
#  Wiki Tag:  <flickrset>photo-set-id</flickrset>
#  Ex :
#    Flickr-Set url: http://www.flickr.com/photos/abarth500/sets/72157624120056693/
#    <flickrset>72157624120056693</flickrset>
#-Tag Image List and Viewer (with Slideshow and Google Maps)
# Featuring a cache
# Right now only with a hardcoded user
#  Wiki Tag:  <flickrtag>tag</flickrtag>
#  Ex :
#    Flickr url: http://www.flickr.com/photos/theplaz/tags/berlin/
#    <flickrtag>berlin</flickrtag>
#-Set Thumbnails and Link
# Tag :
#    <flickrsetthumbs>photo-set-id1,photo-set-id2|PageTitle|LinkText</flickrsetthumbs>
#        *LinkText is optional
# Ex :
#    Flickr-Set url: http://www.flickr.com/photos/abarth500/sets/72157624120056693/
#                    http://www.flickr.com/photos/abarth500/sets/72157624324034434/
#    Link to:        http://shohei.yokoyama.ac/Gallary/Indidnapolis_Motor_Speedway
#    Link text:      CLICK HERE to enter the Photo gallary of Indianapolis Motor Speedway
#    <flickrsetthumbs>72157624120056693,72157624324034434|Gallary/Indidnapolis_Motor_Speedway|CLICK HERE to enter the Photo gallary of Indianapolis Motor Speedway</flickrsetthumbs>
#
# This code is licensed under the Creative Commons Attribution-ShareAlike 3.0 License
# For more information or the latest version visit
# http://shohei.yokoyama.ac/ƒ\ƒtƒgƒEƒFƒA/MediaWiki_Extension/FlickrSet/en
# http://shohei.yokoyama.ac/ƒ\ƒtƒgƒEƒFƒA/MediaWiki_Extension/FlickrSet (Japanses)

/* TODO
static maps of all points
Loading status image
Combine next/show js code
*/
 
 
require_once 'HTTP/Request2.php';
 
 
// User Setting ------------------------------------------------------
//   Flickr
define("wfFLICKRSET_APIKYE", ""); //<----Change!
define("wfFLICKRSET_SECRET", ""); //<--------------------Change!
define("wfFLICKRSET_REST",   "http://api.flickr.com/services/rest/");
 
//   Google Maps V3 API
define("wfFLICKRSET_GMAPURL",'http://maps.google.com/maps/api/js?sensor=false'); //url for full google maps api
define("wfFLICKRSET_GMAPSTATICURL",'http://maps.google.com/maps/api/staticmap?sensor=false'); //url for static google maps API
define("wfUSE_JS_GMAP", FALSE); //if false use only a static google map picture (loads page faster, but not interactive)
 
//   Ext core 3
define("wfFLICKRSET_EXTPATH",'http://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core.js');
//--------------------------------------------------------------------
 
define("wfFLICKRSET_WIDTH",  549);
define("wfFLICKRSET_HEIGHT", 549);
define("wfFLICKRSET_BACKGROUND", "http://farm5.static.flickr.com/4060/4482574753_af9cc46021_o.png");
define("wfFLICKRSET_CACHE",dirname(__FILE__)."/cache/");
 
function wfFlickrSet_getSig($secret, $args){
    ksort($args);
    $s = "";
    foreach($args as $k => $v){
        $s .= $k . $v;
    }
    return md5($secret . $s);
}
 
function wfFlickrSet_callFlickerService($args,$POST = false){
	$args['api_sig'] = wfFlickrSet_getSig(wfFLICKRSET_SECRET, $args);
	$Req = new HTTP_Request2();
	if($POST){
		$Req->setMethod(HTTP_Request2::METHOD_POST);
		$url = FLICKR_REST;
		$Req->addPostParameter($args);
	}else{
		$url = wfFLICKRSET_REST . "?" . http_build_query($args);
	}
	$Req->setUrl($url);
	$res = $Req->send();
	return simplexml_load_string($res->getBody());
}
 
$wgExtensionFunctions[] = 'wfFlickrSet';
$wgExtensionCredits['parserhook'][] = array(
        'name' => 'FlickrSet',
        'description' => 'Display Flickr image sets and tags. Slideshow and Geotag are available.',
        'author' => 'Shohei Yokoyama and Michael Plasmeier',
        'url' => 'http://shohei.yokoyama.ac/'
);
 
function wfFlickrSet() {
        global $wgParser;
        $wgParser->setHook('flickrset', 'renderFlickrSet');
		$wgParser->setHook('flickrtag', 'renderFlickrTag');
		$wgParser->setHook('flickrsetbanner', 'renderFlickrSetThumbs');
		$wgParser->setHook('flickrsetthumbs', 'renderFlickrSetThumbs');//old
}
 
function renderFlickrSetThumbs($input,$arg,&$parser){
	$in = explode("|",$input);
	if(count($in)>=2){
		$page = $in[1];
		$inputs = explode(",",$in[0]);
		foreach($inputs as $i){
			if(!is_numeric($i)){
				return "<strong class='error'>PHOTO-ID ERROR</strong>";
			}
		}
		$input = str_replace(",","-",$in[0]);
	}else{
		return "<strong class='error'>INPUT ERROR</strong>";
	}
	if(count($in)>=3){
		$linkStr = $in[2];
	}else{
		$linkStr = "CLICK HERE to enter the photo gallery of '''".$page."'''";
	}
	$pagelink = $parser->recursiveTagParse("[[".$page."|".$linkStr."]]");
	$oldfile = wfFLICKRSET_CACHE."t+".ltrim($input,"+-");
	$newfile = wfFLICKRSET_CACHE."t-".ltrim($input,"+-");
	if(!strncmp($input,"-",1)){
		$f = $newfile;
		$newfile = $oldfile;
		$oldfile = $f;
	}
	if(is_file($oldfile)){
		unlink($oldfile);
	}
	if(is_file($newfile)){
		$output1 = file_get_contents($newfile);
	}else{
		$imgs=array();$q = 0;
		foreach($inputs as $setid){
			$photoset = wfFlickrSet_callFlickerService(array(
				'method'  => 'flickr.photosets.getPhotos',
				'api_key' => wfFLICKRSET_APIKYE,
				'photoset_id' => $setid,
				'extras' => "url_sq",
				'per_page' => 30,
				'page' => 1,
				'media' => 'photos'
			));
			if((string)$photoset["stat"]!="fail"){
				$imgs[$q]=array();
				foreach($photoset->photoset->photo as $photo){
					$url = (string)$photo["url_sq"];
					array_push($imgs[$q],'<img src="'.$url.'"/>');
				}
			}else{
				$output = "<strong class='error'>FLICKR API ERROR (photoset ID)</strong>";
				return $output;
			}
			$q++;
		}
		$thumbs = array();
		$cc = 0;
		while(count($thumbs) < 30){
			for($c = 0; $c < $q; $c++){
				if(count($imgs[$c])>0){
					array_push($thumbs,array_shift($imgs[$c]));
					if(count($thumbs) >= 30){break;}
				}
			}
			if(count($thumbs) == $cc){
				break;
			}else{
				$cc = count($thumbs);
			}
		}
		$output1 = '<div id="_THUMB_'.$input.'" style="width:'.(count($thumbs)*75).'px;">'.implode("",$thumbs).'</div>';
	}
	$output = "";
	$output2 = "";
	$output0 = "";
	$output0 = '<div style="position:relative;height:79px;margin:0px 20px 20px 20px;padding:0px;background-color:#000;">
	<div id="_TLIST_'.$input.'" style="position:relative;top:0px;left:0px;height:75px;padding:2px 1px 2px 1px;background-color:#000;overflow:hidden;">';
	//$output1 here
	$output2 .= '</div>
	<div style="position:absolute;top:0px;left:0px;"><span style="background-color:#fff;padding:3px 5px 1px 5px;">'.$pagelink.'</span></div>
	</div>
	<script type="text/javascript">
		Ext.onReady(function(){
			Ext.get("_TLIST_'.$input.'").on("mousemove",function(e){
				var d = (e.getPageX()-Ext.get("_TLIST_'.$input.'").getX())/Ext.get("_TLIST_'.$input.'").getWidth();
				var w = Ext.get("_THUMB_'.$input.'").getWidth() - Ext.get("_TLIST_'.$input.'").getWidth();
				Ext.get("_THUMB_'.$input.'").setX(Ext.get("_TLIST_'.$input.'").getX()-Math.ceil(d*w),true);
			},this);
		},this);
	</script>';
	if(FALSE === file_put_contents($newfile,$output1) or $output1 == ""){
		$output = "<strong class='error'>Cache File ".$newfile." ERROR</strong>";
		return $output;
	}
	return $output0.$output1.$output2;
}
 
 
function renderFlickrSet($input) {
	if ( !is_numeric($input)) {
		$output = "<strong class='error'>Flickr Error ( Not a valid ID ): PhotoID ".htmlentities($input, ENT_QUOTES,mb_internal_encoding())." is not numeric</strong>";
		return $output;
	}
	$oldfile = wfFLICKRSET_CACHE."f+".ltrim($input,"+-");
	$newfile = wfFLICKRSET_CACHE."f-".ltrim($input,"+-");
	//theplaz 2010-7-17: if cache off or purge is in the url, bypass cache
	global $wgCachePages;
	//var_dump($wgCachePages);
	if ($wgCachePages != FALSE && $_GET["action"] != 'purge') {
		//echo 'checking cache';
		if(intval($input) > 0){
			$f = $newfile;
			$newfile = $oldfile;
			$oldfile = $f;
		}
		if(is_file($oldfile)){
			unlink($oldfile);
		}
		if(is_file($newfile)){
			//echo 'from cache';
			return file_get_contents($newfile);
		}
	}
	//echo 'new';
	$input = ltrim($input,"+-");
	$photoset_info = wfFlickrSet_callFlickerService(array(
		'method'  => 'flickr.photosets.getInfo',
		'api_key' => wfFLICKRSET_APIKYE,
		'photoset_id' => $input
	));
	$photoset = wfFlickrSet_callFlickerService(array(
		'method'  => 'flickr.photosets.getPhotos',
		'api_key' => wfFLICKRSET_APIKYE,
		'photoset_id' => $input,
		'extras' => "url_sq,url_m",
		'per_page' => 500,
		'page' => 1,
		'media' => 'photos'
	));
	if((string)$photoset["stat"]!="fail"){
		//added theplaz 2010-07-17 Title of flickr item
		$title = '<h3><a href="http://flickr.com"><strong><span style="color:#0063DC">flick</span><span style="color:#EE007B">r</span></strong></a> > <a href="http://flickr.com/photos/'.$photoset->photoset["ownername"].'/sets">'.$photoset->photoset["ownername"].'</a> > <a href="http://www.flickr.com/photos/theplaz/sets/'.$input.'/">'.$photoset_info->photoset->title.' <span style="font-size:12px">Set</span></a></h3>';
		return flickr_common_print($photoset->photoset, $input, $oldfile, $newfile, $title);
	}else{
		$output = "<strong class='error'>FlickrSets: photoset ID not numeric</strong>";
		return $output;
	}
}
//input format: user:tag
//ie theplaz:berlin
function renderFlickrTag($input) {
	//user was not working, just use mine static
	$user = 'theplaz';
	$tag = $input;
 
 
	$oldfile = wfFLICKRSET_CACHE."f+".ltrim($input,"+-");
	$newfile = wfFLICKRSET_CACHE."f-".ltrim($input,"+-");
	//theplaz 2010-7-17: if cache off or purge is in the url, bypass cache
	global $wgCachePages;
	//var_dump($wgCachePages);
	if ($wgCachePages != FALSE && $_GET["action"] != 'purge') {
		//echo 'checking cache';
		if(intval($input) > 0){
			$f = $newfile;
			$newfile = $oldfile;
			$oldfile = $f;
		}
		if(is_file($oldfile)){
			unlink($oldfile);
		}
		if(is_file($newfile)){
			//echo 'from cache';
			return file_get_contents($newfile);
		}
	}
	//echo 'new';
	$input = ltrim($input,"+-");
	/*$user_info = wfFlickrSet_callFlickerService(array(
		'method'  => 'flickr.people.findByUsername',
		'api_key' => wfFLICKRSET_APIKYE,
		'username' => $user
	));
	$nsid = $user_info->user['id'];
	echo $nsid;
	$photoset = wfFlickrSet_callFlickerService(array(
		'method'  => 'flickr.photos.search',
		'api_key' => wfFLICKRSET_APIKYE,
		'user_id' => $nsid,
		'tags' => $tag,
		'per_page' => 500,
		'page' => 1,
		'media' => 'photos'
	));*/
		$photoset = wfFlickrSet_callFlickerService(array(
		'method'  => 'flickr.photos.search',
		'api_key' => wfFLICKRSET_APIKYE,
		'user_id' => '77179348@N00',
		'extras' => "url_sq,url_m",
		'tags' => $tag,
		'per_page' => 500,
		'page' => 1,
		'media' => 'photos'
	));
	if((string)$photoset["stat"]!="fail"){
		//added theplaz 2010-07-17 Title of flickr item
		$title = '<h3><a href="http://flickr.com"><strong><span style="color:#0063DC">flick</span><span style="color:#EE007B">r</span></strong></a> > <a href="http://flickr.com/photos/'.$user.'/sets">'.$user.'</a> > <a href="http://www.flickr.com/photos/'.$user.'/tags/">tags</a> > <a href="http://www.flickr.com/photos/'.$user.'/tags/'.$tag.'/">'.$tag.'</a></h3>';
		return flickr_common_print($photoset->photos, $input, $oldfile, $newfile, $title);
	}else{
		$output = "<strong class='error'>FlickrSets: photoset ID not numeric</strong>";
		return $output;
	}
}
 
function flickr_common_print($photos, $input, $oldfile, $newfile, $title) {
		$output2 = '';
		$output3 = '';
		$output2 = $title;
 
		//print all of the JS needed to run this
		if (wfUSE_JS_GMAP) {
			$output = '<script type="text/javascript" src="'.wfFLICKRSET_GMAPURL.'"></script>';
		}
		$output = '<script type="text/javascript" src="'.wfFLICKRSET_EXTPATH.'"></script>
		<script type="text/javascript">
		var jsFLICKRSET_sel_'.$input.' = 0;
		var jsFLICKRSET_swap_'.$input.' = true;
		var jsFLICKRSET_runner_'.$input.' = new Ext.util.TaskRunner();
		var jsFLICKRSET_task_'.$input.' = {run:function(){
				jsFLICKRSET_next_'.$input.'();
				},scope:this,interval:5000};
		var jsFLICKRSET_started_'.$input.' = false;
		var jsFLICKRSET_mapped_'.$input.' = false;
		var jsFLICKRSET_STATIC_GMAP_ROOT'.$input.' = "'.wfFLICKRSET_GMAPSTATICURL.'";
		';
		// FUNCTION showmap ------------------------------------------------------------
		$output .= 'function jsFLICKRSET_showmap_'.$input.'(){
			if(jsFLICKRSET_mapped_'.$input.'){ //close
				var top = Ext.get("_BASE'.$input.'").getTop() - '.wfFLICKRSET_HEIGHT.';
				Ext.get("_MAP'.$input.'").setY(top,true);
				Ext.getDom("_SHOWMAPa'.$input.'").style.color="#aaaaaa";
			}else{ //open
				var top = Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2);
				Ext.get("_MAP'.$input.'").setY(top,true);
				Ext.getDom("_SHOWMAPa'.$input.'").style.color="#ff8888";
			}
			jsFLICKRSET_mapped_'.$input.'=!jsFLICKRSET_mapped_'.$input.'; //flip the bit
		}
		';
		// FUNCTION slideshow ------------------------------------------------------------
		$output.= 'function jsFLICKRSET_slideshow_'.$input.'(){
			if(jsFLICKRSET_started_'.$input.'){
				jsFLICKRSET_runner_'.$input.'.stop(jsFLICKRSET_task_'.$input.');
				Ext.getDom("_SLIDESHOW'.$input.'").style.color="#aaaaaa";
			}else{
				jsFLICKRSET_runner_'.$input.'.start(jsFLICKRSET_task_'.$input.');
				Ext.getDom("_SLIDESHOW'.$input.'").style.color="#ff8888";
			}
			jsFLICKRSET_started_'.$input.'=!jsFLICKRSET_started_'.$input.';
		}
		';
		// FUNCTION next ------------------------------------------------------------
		$output.= 'function jsFLICKRSET_next_'.$input.'(){
			var imgidnew = "_'.$input.'_A";
			var imgidold = "_'.$input.'_B";
				if(jsFLICKRSET_swap_'.$input.'){
				imgidnew="_'.$input.'_B";
				imgidold="_'.$input.'_A";
			}
			jsFLICKRSET_swap_'.$input.'=!jsFLICKRSET_swap_'.$input.';
			var info = jsFLICKRSET_info_'.$input.'(jsFLICKRSET_sel_'.$input.');
			Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setStyle("border-color","#fff");
			Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setOpacity(0.3,true);
			jsFLICKRSET_sel_'.$input.'++;
			if(jsFLICKRSET_sel_'.$input.'>=jsFLICKRSET_num_'.$input.'){
				jsFLICKRSET_sel_'.$input.'=0;
			}
			Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setStyle("border-color","#ff0000");
			info = jsFLICKRSET_info_'.$input.'(jsFLICKRSET_sel_'.$input.');
			var left = Ext.get("_BASE'.$input.'").getLeft() + Math.floor(('.wfFLICKRSET_WIDTH.'-info["width"])/2);
			var top = Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-info["height"])/2);';
			if (wfUSE_JS_GMAP) {
				$output .= 'if(info["geo"]){
					map'.$input.'.setCenter(new google.maps.LatLng(info["latitude"],info["longitude"]));
					marker'.$input.'.setPosition(new google.maps.LatLng(info["latitude"],info["longitude"]));
					if(jsFLICKRSET_mapped_'.$input.'){
						Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
					}
				}else{
					Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
				}';
			} else {
				$output .= 'if(info["geo"]){
					static_map_url = "&zoom=13&size=500x500&markers=size:mid|"+info["latitude"]+","+info["longitude"];
					Ext.get("_STATIC_MAP'.$input.'").set({src:  "'.wfFLICKRSET_GMAPSTATICURL.'"+html_decode(static_map_url)});
					if(jsFLICKRSET_mapped_'.$input.') {//if map is open
						Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
					}
				}else{
					Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
				}';
			}
			$output .= 'Ext.getDom("_'.$input.'_title").innerHTML = info["title"];
			Ext.getDom("_'.$input.'_description").innerHTML = info["description"];
			Ext.getDom("_'.$input.'_description").style.visibility = (info["description"]=="")?"hidden":"visible";
			Ext.getDom("_SHOWMAP'.$input.'").style.visibility = (info["geo"])?"visible":"hidden";
			Ext.get(imgidnew).setXY([left + '.wfFLICKRSET_WIDTH.',top]);
			Ext.get(imgidnew).setOpacity(1,true);
			Ext.get(imgidnew).setXY([left,top],true);
			Ext.get(imgidold).setOpacity(0,{callback:function(){
			var info = jsFLICKRSET_info_'.$input.'(1+jsFLICKRSET_sel_'.$input.');Ext.getDom(imgidold).src=info["url"];},scope:this});
		}
		';
		// FUNCTION show ------------------------------------------------------------
		$output.= 'function jsFLICKRSET_show_'.$input.'(id,url){
			var imgidnew = "_'.$input.'_A";var imgidold = "_'.$input.'_B";
			if(jsFLICKRSET_swap_'.$input.'){
				imgidnew="_'.$input.'_B";
				imgidold="_'.$input.'_A";
			}
			Ext.getDom(imgidold).src = url;
			Ext.get("_'.$input.'_"+id).setStyle("border-color","#ff0000");
			Ext.get("_'.$input.'_"+id).setOpacity(0.3,true);
			Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setStyle("border-color","#fff");
			Ext.get("_'.$input.'_"+jsFLICKRSET_sel_'.$input.').setOpacity(0.3,true);
			var info = jsFLICKRSET_info_'.$input.'(id);
			var left = Ext.get("_BASE'.$input.'").getLeft() + Math.floor(('.wfFLICKRSET_WIDTH.'-info["width"])/2);
			var top = Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-info["height"])/2);';
			if (wfUSE_JS_GMAP) {
				$output .= 'if(info["geo"]){
					map'.$input.'.setCenter(new google.maps.LatLng(info["latitude"],info["longitude"]));
					marker'.$input.'.setPosition(new google.maps.LatLng(info["latitude"],info["longitude"]));
					if(jsFLICKRSET_mapped_'.$input.'){
						Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
					}
				}else{
					Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
				}';
			} else {
				$output .= 'if(info["geo"]){
					static_map_url = "&zoom=13&size=500x500&markers=size:mid|"+info["latitude"]+","+info["longitude"];
					Ext.get("_STATIC_MAP'.$input.'").set({src:  "'.wfFLICKRSET_GMAPSTATICURL.'"+html_decode(static_map_url)});
					if(jsFLICKRSET_mapped_'.$input.') {
						Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() + Math.floor(('.wfFLICKRSET_HEIGHT.'-500)/2),true);
					}
				}else{
					Ext.get("_MAP'.$input.'").setY(Ext.get("_BASE'.$input.'").getTop() -'.wfFLICKRSET_HEIGHT.',true);
				}';
			}
			$output .= 'Ext.getDom("_'.$input.'_title").innerHTML = info["title"];
			Ext.getDom("_'.$input.'_description").innerHTML = info["description"];
			Ext.getDom("_'.$input.'_description").style.visibility = (info["description"]=="")?"hidden":"visible";
			Ext.getDom("_SHOWMAP'.$input.'").style.visibility = (info["geo"])?"visible":"hidden";
			Ext.get(imgidold).setXY([left,top],true);
			info = jsFLICKRSET_info_'.$input.'(id+1);
			Ext.getDom(imgidnew).src = info["url"];
			jsFLICKRSET_sel_'.$input.' = id;
		}
		function jsFLICKRSET_info_'.$input.'(id){switch(id){';
		$c = 0;
		$lat=37.4419;$lon=-122.1419;
		$LAT=37.4419;$LON=-122.1419;
		foreach($photos->photo as $photo){
			$photoinfo = wfFlickrSet_callFlickerService(array(
				'method'  => 'flickr.photos.getInfo',
				'api_key' => wfFLICKRSET_APIKYE,
				'photo_id' => (string)$photo["id"]
			));
			$phototitle = htmlentities((string)$photoinfo->photo->title, ENT_QUOTES,mb_internal_encoding());
			$photodescription = htmlentities((string)$photoinfo->photo->description, ENT_QUOTES,mb_internal_encoding());
			$photosizes = wfFlickrSet_callFlickerService(array(
				'method'  => 'flickr.photos.getSizes',
				'api_key' => wfFLICKRSET_APIKYE,
				'photo_id' => (string)$photo["id"]
			));
			$url = (string)$photo["url_m"];
			$width = 500;
			$height = 500;
			if((string)$photosizes["stat"]!="fail"){
				foreach($photosizes->sizes->size as $size){
					$url = $size["source"];
					$width = $size["width"];
					$height = $size["height"];
					if((string)$size["label"] == "Medium"){
						break;
					}
				}
			}
			$geo = "false";
			$visGeo = "hidden";
			if(isset($photoinfo->photo->location)){
				$geo = "true,'latitude':".(string)$photoinfo->photo->location["latitude"].",'longitude':".(string)$photoinfo->photo->location["longitude"];
				$lat = floatval((string)$photoinfo->photo->location["latitude"]);
				$lon = floatval((string)$photoinfo->photo->location["longitude"]);
				$visGeo = "visible";
			}
			$output  .= 'case '.$c.':return {"url":"'.$url.'","title":"'.htmlentities($phototitle).'","description":"'.htmlentities(nl2brr($photodescription)).'","width":'.$width.',"height":'.$height.',"geo":'.$geo.'};
			';
			$col = "#fff";
			if($c == 0){
				$LAT = $lat;
				$LON = $lon;
				$col ="#f00";
				$output2 .= '<div id="_BASE'.$input.'" style="position:relative;top:0px;left:0px;overflow:hidden;width:'.wfFLICKRSET_WIDTH.'px;height:'.wfFLICKRSET_WIDTH.'px;background-color:#000;border: 1px solid #ffffff;margin:1px;float:left;">
				<div id="_'.$input.'_title" style="z-index:105;position:absolute;top:0px;left:0px;color:#fff;font-weight:bold;font-size:large;padding:5px;">'.$phototitle.'</div>
				';
				$visDescription = "hidden";
				if($photodescription!=""){
					$visDescription = "visible";
				}
				$output2 .= '<div style="background-color:#00f;position:absolute;z-index:103;width:500px;height:500px;top:-'.(wfFLICKRSET_HEIGHT+10).'px;left:'.floor((wfFLICKRSET_WIDTH-500)/2).'px;"><div style="width:500px;height:500px;" id="_MAP'.$input.'">';
				if (!wfUSE_JS_GMAP) {
					$output2 .= '<img id="_STATIC_MAP'.$input.'" src="" />';
				}
				$output2 .= '</div></div><div id="_'.$input.'_description" style="visibility:'.$visDescription.';border:1px dotted #fff;z-index:104;background-image:url('.wfFLICKRSET_BACKGROUND.');position:absolute;top:0px;width:'.(wfFLICKRSET_WIDTH-120).'px;margin:55px 50px 0px 50px;left:0px;padding:5px 10px 5px 10px;text-justify:inter-ideograph;color:#fff;">'.$photodescription.'</div>
				<div style="z-index:102;color:#aaa;position:absolute;top:0px;left:'.(wfFLICKRSET_WIDTH-65).'px;">'."[<a id=\"_SLIDESHOW".$input."\" href=\"#\" onclick=\"jsFLICKRSET_slideshow_".$input."();return false;\" style=\"color:#aaa;\">Slideshow</a>]".'</div>
				<div id="_SHOWMAP'.$input.'" style="visibility:'.$visGeo.';z-index:101;color:#aaa;position:absolute;top:0px;left:'.(wfFLICKRSET_WIDTH-100).'px;">'."[<a id=\"_SHOWMAPa".$input."\" style=\"color:#aaa;\" href=\"#\" onclick=\"jsFLICKRSET_showmap_".$input."();return false;\" style=\"color:#aaa;\">Map</a>]".'</div>
				<img onclick="jsFLICKRSET_next_'.$input.'();" style="z-index:100;position:absolute;left:'.floor((wfFLICKRSET_WIDTH-$width)/2).'px;top:'.floor((wfFLICKRSET_HEIGHT-$height)/2).'px;" id="_'.$input.'_A" src="'.(string)$photo["url_m"].'"/>';
			}
			if($c == 1){
				$output2 .= '<img onclick="jsFLICKRSET_next_'.$input.'();" style="z-index:99;position:absolute;left:'.(wfFLICKRSET_WIDTH*2).'px;top:'.floor((wfFLICKRSET_HEIGHT-$height)/2).'px;" id="_'.$input.'_B" src="'.(string)$photo["url_m"].'"/>
				</div>';
			}
			$id = '_'.$input.'_'.$c;
			$output3 .= '<img style="border: 1px solid '.$col.';margin:1px" onclick="jsFLICKRSET_show_'.$input.'('.$c.',\''.(string)$photo["url_m"].'\');" id="'.$id.'" style="margin:1px;" src="'.(string)$photo["url_sq"].'"/>';
			$c++;
		}
		$output  .= 'default:return jsFLICKRSET_info_'.$input.'(0);}}
		            var jsFLICKRSET_num_'.$input.' = '.$c.';';
		if (wfUSE_JS_GMAP) {			
					$output .= 'Ext.onReady(function(){
						map'.$input.' = new google.maps.Map(document.getElementById("_MAP'.$input.'"), {
						zoom:13,center:new google.maps.LatLng('.$LAT.','.$LON.'),
						mapTypeId:google.maps.MapTypeId.ROADMAP,
						mapTypeControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT,style:google.maps.MapTypeControlStyle.DROPDOWN_MENU},
						navigationControlOptions:{position:google.maps.ControlPosition.TOP_LEFT,style:google.maps.NavigationControlStyle.SMALL}
					});
					marker'.$input.' = new google.maps.Marker({clickable:false,position:new google.maps.LatLng('.$LAT.','.$LON.'),map:map'.$input.'});
					},this);';
		} else {
			//init with first img info
			$output .= 'static_map_url = "&zoom=13&size=500x500&markers=size:mid|'.$LAT.','.$LON.'";
			Ext.onReady(function(){
				Ext.get("_STATIC_MAP'.$input.'").set({src:  "'.wfFLICKRSET_GMAPSTATICURL.'"+html_decode(static_map_url)});
			});
			';
		}
		$output .= '</script>
					<p>';
		$output3 .= "<br clear='all'>";
		if(FALSE === file_put_contents($newfile,$output.$output2.$output3)){
			$output = "<strong class='error'>FlickrSets: Error writing cache file: ".$newfile."</strong>";
			return $output.$output2.$output3;
		}
		return $output.$output2.$output3;
 
}
 
function nl2brr($text)
{
    return preg_replace("/\r\n|\n|\r/", "<br>", $text);
}
 
?>