===== Photo Organizer Webservice ===== By Luud Heck, April 2007 ** NOTE: at this moment this page is little more than a dump of some things I've tested and proven to work. I have made further advances already and will update this page as soon as possible. ** ==== Introduction ==== I've long wanted to include photos in my web pages without having to copy them over from PO. It is much nicer when you can include the images straight from PO. In a way this has long been possible by abusing the image.display.php file in your page. However, it is a rather rigid method and only allows to include a single photo at a time. Below I explain how I publish my websites with MediaWiki and include Photo Organizer photos and albums in my wiki pages. The crux is that the information about photos and albums will be provided by Photo Organiser as a SOAP based webservice. ==== MediaWiki ==== === Homepages in MediaWiki === [[http://www.mediawiki.org|MediaWiki]] can be very useful for maintaining a website, even if your website is not an encyclopedia like [[http://www.wikipedia.org|wikipidia]]. Here are some examples and resources to show you how: * [[http://tango.freedesktop.org|Tango webpages]] * [[http://meta.wikimedia.org/wiki/Gallery_of_user_styles|MediaWiki Gallery of user styles]] * [[http://stefan.agentfarms.net/index.php/Personal_Page_with_Mediawiki|Stefan Urbanek]] * [[http://meta.wikimedia.org/wiki/Skins|MediaWiki Skins]] * [[http://www.alistapart.com/articles/negativemargins/|A List Apart]] (This explains the technique used in the monobook mediawiki skin.) The above in nice and all, but what has it to do with Photo Organizer? Well, assuming we are creating our own webpages in MediaWiki, how are we going to include our photos and albums from Photo Organizer in our pages? In case of MediaWiki, this is not very hard. All we have to do is create an extension for MediaWiki that drags in the photos and albums from Photo Organizer. The good thing is that Photo Organizer and MediaWiki do not need to be on the same host. But we come back to that later. === MediaWiki Extension === Creating a [[http://meta.wikimedia.org/wiki/MediaWiki_extensions_FAQ|MediaWiki extension]] is quite easy and explained in the [[http://meta.wikimedia.org/wiki/Extending_wiki_markup|MediaWiki]] documentation. For our purpose I extended the MediaWiki markup with the tag. So including Photo Organizer in a wiki page will look like: = My holiday trip = Hello all, here are some photos from my holiday trip: All we have to do is include a simple element with some attributes telling our extension what to include (in this case an album with id 163 in thumbnail view). Here is an example MediaWiki extension for Photo Organizer. This example just generates some fixed html and does not retrieve any information from the Photo Organizer webservice yet. It is just to show how extend the wiki markup. some text * the function registered by the extension gets the text between the * tags as input and can transform it into arbitrary HTML code. * Note: The output is not interpreted as WikiText but directly * included in the HTML output. So Wiki markup is not supported. * * * Activating the extension * ------------------------ * * To activate the extension, include it at the end of LocalSettings.php: * * require_once("extensions/PhotoOrganizer.php"); * * * Usage * ----- * */ $wgExtensionFunctions[] = "wfPhotoOrganizerExtension"; /* * Register the Photo Organizer Extension */ function wfPhotoOrganizerExtension() { global $wgParser; /* Register the extension with the WikiText parser. * * The first parameter is the name of the new tag. * In this case it defines the tag ... * * The second parameter is the callback function for * processing the text between the tags. */ $wgParser->setHook( "po", "renderPhotoOrganizer" ); } /* * The callback function for converting the input text to HTML output * * This extension will simply discard any text in the tag, i.e. $input * will be ignored. * * However, the attributes of the tag are parsed as provided in the $argv * parameter. * * The following paramters are accepted: * * mode Specifies the type of PO inclusion. * Possible values: * photo: include a single photo * album: include a complete album * style Specifies the style to use for rendering. * Possible values: * thumbnail: photos are displayed as thumbnail images * preview : photos are displayes as preview * (photo mode only) * list : photos are only displayed by their name * (album mode only) * id Specifies the database reference id of the photo or album. * * A typical use of the Photo Organizer tag will look like: * * */ function renderPhotoOrganizer( $input, $argv, &$parser ) { /* * Disable caching for this extension as we want the latest information * that is available from Photo Organizer. */ $parser->disableCache(); /* * For testing, just render a heading 1 and display the attributes */ $output = "

Photo Organizer Extension

\n"; $output .= "
\n";
    $output .= print_r( $argv, true );
    $output .= "
\n"; /* * Make sure we are alone: */ $output .= "
\n"; /* * Start the containing box for the album */ $output .= "
\n"; /* * Float all thumbnails inside the album div * * Getting images centered vertically is not too trivial. * * Images are inline elements. The css way would be to set the display * style of the container div to table-cell and use the vertical-align * property set to middle. However, not all browsers support this * correctly (note: IE). A solution is to embed each image in a single * cell table. This table inherits it's size from it's container div and * can have the td element's vertical-align property set to middle. * * The html will now look as: * *
* * * * *
* *
*
* * And the CSS for this will look like * * .po_thumnail { * } * * div.po_thumbnail { * float: left; * border: 1px solid gray; * padding: 3px; * margin: 3px; * } * * table.po_thumbnail, tr.po_thumbnail, td.po_thumbnail { * * border: 0px; * margin: 0px; * padding: 0px; * widht: 100%; * height: 100%; * } * * td.po_thumnail { * text-align: center; * vertical-align: middle; * } */ for ( $i=1; $i<40; $i++ ) { $output .= "
"; $output .= "
"; $output .= ""; $output .= "
"; $output .= "
\n"; } /* * Make the album div grow to the size of it's contents */ $output .= "
\n"; /* * Close the album div */ $output .= "
\n"; return $output; } ?>
Here is the CSS file that needs to be imported in the wiki skin CSS file (use the import directive and place it at the start of the main.css file in the monobook skin for example). /* * Photo Organizer Extension Styling */ /* * Do not float the album container, but keep it an inline element! */ div.po_album { float: none; width: 100%; /* background-color: yellow; border: 1px solid red; */ clear:both; } .po_thumbnail { margin: 0px; padding: 0px; } /* * Make sure to float the thumnails (left or right). */ div.po_thumbnail { float: left; border: 0px solid gray; padding: 3px; margin: 3px; } table.po_thumbnail, tr.po_thumnail, td.po_thumnail { /* border: 1px solid red; */ border: 0px; padding: 0px; margin: 0px; width: 100%; height: 100%; } td.po_thumbnail { text-align: center; vertical-align: middle; } img.po_thumbnail { border: 1px solid black; } ==== Photo Organizer SOAP interface ==== Having the basics of creating a MediaWiki extension for Photo Organizer working, lets look at how we can make this extension retrieve information from the Photo Organizer database. === PHP-SOAP === Recent versions of PHP include good support for the SOAP protocol in the form of the [[http://www.php.net/manual/en/ref.soap.php|PHP-SOAP]] extension of PHP. Now, before you start experimenting, take this TIP and follow it! **Make sure to disable WSDL caching in both client and server, and check every time that it is still there! ** ini_set('soap.wsdl_cache_enabled', '0'); I thought I had it disabled, but trying things and starting over once in a while resulted in not having WSDL caching disabled in my client. This oversight has cost me a couple of evenings getting thing to work right. Next tip: ** Validate your WSDL file! ** If you have Mono installed on your Linux box you can use the wsdl command. Here is an example static serverice that generates some kind of Photo Organizer album information. This is just a demonstration, not a functional solution for PO yet. Just put in in a directory wsdl-po on your PHP with SOAP enabled webserver and it should work if you browse to the client.php file. photoorganizer.wsdl common.php "C_PhotoInfo" ); ?> photoinfo.php photoserver.php id = 42; $l_PhotoInfo->title = 'Photo Title 1 in album ['.$id.'].'; $l_PhotoInfoList[0] = $l_PhotoInfo; $l_PhotoInfo = new C_PhotoInfo(); $l_PhotoInfo->id = 1024; $l_PhotoInfo->title = 'Photo Title 2 in album ['.$id.'].'; $l_PhotoInfoList[1] = $l_PhotoInfo; return $l_PhotoInfoList; // return $l_PhotoInfo; } } ?> server.php 1, 'classmap' => $photoClassMap ) ); $s->setClass('C_PhotoOrganizerService'); $s->handle(); ?> client.php
link = new SoapClient(
            $wsdl,
            array(
                'trace' => 1,
                'classmap' => $photoClassMap
            )
        );
    }

    public function getAlbum($id)
    {
        // $l_Album = array();

        try {
            $l_Album = $this->link->getAlbum($id);

            echo "var_dump:\n=========\n";
            var_dump ($l_Album);

            echo "Iterate array\n=============\n";

            // If only one element is returned, an array won't be built
            if (is_array($l_Album))
            {
                echo "It's an array!";

                $i = 1;
                foreach ($l_Album as $photo)
                {
                    echo "\n\nPrinting element $i:\n-------------------\n";
                    print_r ($photo);
                    $i++;
                }
                echo "\n";

            } else {
                print_r ($l_Album);
            }
        }
        catch (SoapFault $sf)
        {
            print_r ($sf->getMessage());
            $this->debug();
        }
            $this->debug();
    }

    public function debug()
    {
        echo "Types:\n";
        print_r ($this->link->__getTypes());
        echo "Request:\n";
        echo htmlspecialchars(str_replace('>', ">\n", $this->link->__getLastRequest())), "\n";
        echo "Response:\n";
        echo htmlspecialchars(str_replace('>', ">\n", $this->link->__getLastResponse())), "\n";
    }

}

ini_set('soap.wsdl_cache_enabled', '0');

echo "Running client...\n\n";

echo "Calling server...\n";

$client = new client($wsdlfile);
$client->getAlbum(27);

echo "\nDone.\n";

?>