root/albumembed/AlbumEmbed.php

Revision 280, 14.5 KB (checked in by m, 21 months ago)

IE6 Layout fixes.

  • Property svn:keywords set to Id Rev
Line 
1<?php
2
3    // +----------------------------------------------------------------------+
4    // | Embed a Web album in your website                                    |
5    // +----------------------------------------------------------------------+
6    // | Copyright (c) Markus Tacker <m@tacker.org>                           |
7    // +----------------------------------------------------------------------+
8    // | This library is free software; you can redistribute it and/or        |
9    // | modify it under the terms of the GNU Lesser General Public           |
10    // | License as published by the Free Software Foundation; either         |
11    // | version 2.1 of the License, or (at your option) any later version.   |
12    // |                                                                      |
13    // | This library is distributed in the hope that it will be useful,      |
14    // | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
16    // | Lesser General Public License for more details.                      |
17    // |                                                                      |
18    // | You should have received a copy of the GNU Lesser General Public     |
19    // | License along with this library; if not, write to the                |
20    // | Free Software Foundation, Inc.                                       |
21    // | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA               |
22    // +----------------------------------------------------------------------+
23
24    // Some PEAR packages are required
25    // Installation is out of the scope of this script. Please refer to
26    // http://pear.php.net
27    // XML_RSS must be version >=0.9.10
28    require_once 'Cache/Lite.php';
29    require_once 'XML/RSS.php';
30    require_once 'AlbumEmbed/Exception.php';
31
32    /**
33    * Embed a Web album in your website
34    *
35    * @package AlbumEmbed
36    * @author Markus Tacker <m@tacker.org>
37    * @version $Id$
38    */
39    abstract class AlbumEmbed
40    {
41        const ID_NEXT = 1;
42        const ID_PREV = 2;
43        const ID_RESPONSE = 3;
44
45        /**
46        * Options for PEAR::Cache_Lite
47        *
48        * @see http://pear.php.net/manual/en/package.caching.cache-lite.cache-lite.cache-lite.php
49        */
50        static $cache_options = array(
51            'lifeTime' => 86400,
52            'automaticSerialization' => true,
53            'errorHandlingAPIBreak' => true,
54        );
55
56        protected $rss_url;
57        protected $images;
58
59        /**
60        * Enable preloading of images
61        *
62        * @var bool
63        */
64        static $preload = true;
65
66        /**
67        * The location of this file, may be relative, absolute or even URL
68        *
69        * @var string
70        */
71        static $location;
72
73        /**
74        * Factory
75        *
76        * @param RSS url
77        */
78        static function factory($rss_url)
79        {
80            $class = false;
81            if (preg_match('%^http://picasaweb\.google\.com/data/feed/base/user/%i', $rss_url)) {
82                $class = 'Picasa';
83            } elseif (stristr($rss_url, 'main.php?g2_view=rss.SimpleRender')) {
84                $class = 'Gallery2';
85            }
86            if (!$class) {
87                throw new AlbumEmbed_Exception('Invalid RSS feed.');
88            }
89            $class = __CLASS__ . '_' . $class;
90            require_once $file = dirname(__FILE__) . '/' . str_replace('_', '/', $class) . '.php';
91            return new $class($rss_url);
92        }
93
94        /**
95        * Constructor
96        */
97        protected function __construct($rss_url)
98        {
99            $this->rss_url = $rss_url;
100            if (empty(self::$location)) self::$location = ((isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/' . basename(__FILE__);
101        }
102
103        abstract protected function getImagesFromRss();
104
105        final protected function getImages()
106        {
107            if (!is_null($this->images)) return $this->images;
108            self::$cache_options['cacheDir'] = dirname(__FILE__) . '/cache/';
109            $Cache = new Cache_Lite(self::$cache_options);
110            if ($images = $Cache->get($this->rss_url, 'images')) {
111                $this->images = $images;
112                return $images;
113            }
114            $images = $this->getImagesFromRss();
115
116            if (ini_get('allow_url_fopen')) {
117                foreach ($images as $k => $image) {
118                    if (preg_match('/src="([^"]+)"/i', $image['img_html'], $match)) {
119                        // Cache Image
120                        $req = parse_url($match[1]);
121                        $image_cache = '/cache/images/' . md5($match[1]) . '.' . substr(basename($req['path']), strrpos(basename($req['path']), '.') + 1);
122                        $local_image_file = dirname(__FILE__) . $image_cache;
123                        if (!file_exists($local_image_file)) {
124                            copy($match[1], $local_image_file);
125                        }
126                        $images[$k]['img_html'] = str_replace($match[0], 'src="' . dirname(self::$location) . $image_cache . '"', $images[$k]['img_html']);
127                        // Fix missin alt attributes
128                        if (!stristr( $images[$k]['img_html'], 'alt=')) {
129                            $images[$k]['img_html'] = str_replace('src=', 'alt="" src=', $images[$k]['img_html']);
130                        }
131                        // Calculate orientation
132                        $image_size = getimagesize($local_image_file);
133                        $images[$k]['orientation'] = ($image_size[0] >= $image_size[1]) ? 'landscape' : 'portrait';
134                    }
135                }
136            }
137            if (empty($images)) throw new AlbumEmbed_Exception('No images found.');
138            $result = $Cache->save($images, $this->rss_url, 'images');
139            if ($result !== true) {
140                throw new AlbumEmbed_Exception('Cache error: ' . $result->getMessage());
141            }
142            return $images;
143        }
144
145        function getItemCode($current_item = 0, $static = false, $class = null)
146        {
147            if (is_null($class)) $class = 'albumembed';
148            $class .= ' ' . strtolower(str_replace('_', '-', get_class($this)));
149            try {
150                $images = $this->getImages();
151
152                $n_items = count($images);
153                if (!isset($images[$current_item])) {
154                    $current_item = count($images) - 1;
155                }
156                $image = $images[$current_item];
157                $id = $this->getId();
158
159                $url = parse_url($_SERVER['REQUEST_URI']);
160
161                if (isset($url['query'])) {
162                    parse_str($url['query'], $query);
163                    if (isset($query[$id])) {
164                        unset($query[$id]);
165                    }
166                } else {
167                    $query = array();
168                }
169                $query[$id] = '';
170                $params = array();
171                foreach ($query as $k => $v) {
172                    $params[] = $k . '=' . $v;
173                }
174                $req = '?' . join('&amp;', $params);
175
176                // Create Div
177                $return = '';
178                if ($static) $return = '<div class="' . $class. '" id="' . $id . '">';
179                $return .= '<div class="box ' . $image['orientation'] . '"><ul><li class="prev" id="' . $this->getId(self::ID_PREV) . '">';
180                if ($current_item > 0) {
181                    $return .= ($static) ? '<a href="' . $req . ($current_item - 1) . '#' . $id . '">' : '';
182                    $return .= '&lt;';
183                    $return .= ($static) ? '</a>' : '';
184                }
185                $return .= '</li>'
186                . '<li class="foto"><a href="' . $image['link'] . '">' . (($image['img_html']) ? $image['img_html'] : 'No image.') . '</a></li>'
187                . '<li class="next" id="' . $this->getId(self::ID_NEXT) . '">';
188                if ($current_item < $n_items - 1) {
189                    $return .= ($static) ? '<a href="' . $req . ($current_item + 1) . '#' . $id . '">' : '';
190                    $return .= '&gt;';
191                    $return .= ($static) ? '</a>' : '';
192                }
193                $return .= '</li></ul>'
194                . '<p class="caption">' . (($image['title']) ? htmlspecialchars($image['title']) : '&nbsp;') . '</p><p class="info">' . ($current_item + 1) . ' / ' . $n_items . '</p>'
195                . '</div>';
196                if ($static) $return .= "</div>\n";
197                return $return;
198            } catch (AlbumEmbed_Exception $E) {
199                return '<p>' . $E->getMessage() . '</p>';
200            }
201        }
202
203        /**
204        * Returns the ID for the current embedded gallery
205        *
206        * @param int ID type
207        * @return string
208        */
209        function getId($type = null)
210        {
211            $return = 'albumembed_' . md5($this->rss_url);
212            switch ($type) {
213            case self::ID_NEXT:
214                $return .= '_next';
215                break;
216            case self::ID_PREV:
217                $return .= '_prev';
218                break;
219            case self::ID_RESPONSE:
220                $return .= 'Response';
221                break;
222            }
223            return $return;
224        }
225
226        /**
227        * Returns the required javascript code
228        */
229        function getJsCode()
230        {
231            try {
232                $return = '<script type="text/javascript"><!--//--><![CDATA[//><!--' . "\n"
233                . 'function ' . $this->getId(self::ID_RESPONSE) . " (originalRequest) {"
234                . '    $(\'' . $this->getId() . "').innerHTML = originalRequest.responseText;"
235                . "    if (\$('". $this->getId(self::ID_NEXT) . "')) { \$('". $this->getId(self::ID_NEXT) . "').onclick = function () {"
236                . $this->getActionJs('+')
237                . "    }};"
238                . "    if (\$('". $this->getId(self::ID_PREV) . "')) { \$('". $this->getId(self::ID_PREV) . "').onclick = function () {"
239                . $this->getActionJs('-')
240                . "    }};"
241                . "};"
242                . "function WindowOnload(f) {" // See http://blog.firetree.net/2005/07/17/javascript-onload/
243                . "    var prev = window.onload;"
244                . "    window.onload=function() { if(prev) prev(); f(); };"
245                . "};"
246                . "WindowOnload(function () {"
247                . $this->getActionJs();
248                if (self::$preload) {
249                    $return .= "var ImagePreload = new Array();";
250                    $n = 0;
251                    foreach ($this->getImages() as $image) {
252                        $url = preg_match('/src="([^"]+)"/iU', $image['img_html'], $match);
253                        if (!isset($match[1])) continue;
254                        $return .= "ImagePreload[$n] = new Image();"
255                        . "ImagePreload[$n].src = '{$match[1]}';";
256                        $n++;
257                    }
258                }
259                $return .= "});\n";
260                $return .= "//--><!]]></script>\n";
261                return $return;
262            } catch (AlbumEmbed_Exception $E) {
263                return '';
264            }
265        }
266
267        protected function getActionJs($item = 0)
268        {
269            return "var request= { albumembed__rss_url: '" . $this->rss_url . "',albumembed__item: '" . $item . "',albumembed__location: '" . self::$location . "'}; "
270            . "var query = \$H(request);"
271            . "var GridRequest = new Ajax.Request("
272            . "    '" . self::$location . "',"
273            . "    {"
274            . "        method: 'get',"
275            . "        parameters: query.toQueryString(),"
276            . "        onFailure: function() { alert(msg); },"
277            . "        onComplete: function(originalResponse){" . $this->getId(self::ID_RESPONSE) . "(originalResponse);}"
278            . "    }"
279            . ");";
280        }
281
282        /**
283        * Returns the required HTML and JS
284        *
285        * @return string
286        * @param string optional alternate class name
287        */
288        static function getContainer($rss_url, $class = 'albumembed')
289        {
290            $Embed = AlbumEmbed::factory($rss_url);
291            $id = $Embed->getId();
292            $item = (isset($_REQUEST[$id])) ? (int)$_REQUEST[$id] : 0;
293            @session_start();
294            $_SESSION[$id] = $item;
295            $return = $Embed->getItemCode($item, true, $class);
296            $return .= $Embed->getJSCode();
297
298            return "<!-- <<< \n"
299            . "Embedded Album created with \n"
300            . 'AlbumEmbed $Rev$ by Markus Tacker ( http://m.tacker.org/blog/ ).' . "\n"
301            . "-->\n"
302            . $return
303            . "<!-- >>> -->\n";
304        }
305
306        /**
307        * Returns the number of items
308        *
309        * @return int
310        */
311        function countImages()
312        {
313            return count($this->getImages());
314        }
315
316        /**
317        * Main function.
318        */
319        static function main()
320        {
321            self::ajax();
322        }
323
324        protected static function ajax()
325        {
326            if (isset($_REQUEST['albumembed__location'])) {
327                self::$location = $_REQUEST['albumembed__location'];
328            }
329            if (isset($_REQUEST['albumembed__rss_url'])) {
330                @session_start();
331                try {
332                    $Embed = AlbumEmbed::factory($_REQUEST['albumembed__rss_url']);
333                    $id = $Embed->getId();
334                    if (!isset($_SESSION[$id])) {
335                        $_SESSION[$id] = 0;
336                    }
337                    if (!isset($_SESSION[$id . 'max'])) {
338                        $_SESSION[$id . 'max'] = $Embed->countImages();
339                    }
340                    switch ($_REQUEST['albumembed__item']) {
341                    case '+':
342                        if ($_SESSION[$id] < $_SESSION[$id . 'max'] - 1) {
343                            $_SESSION[$id]++;
344                        }
345                        break;
346                    case '-':
347                        if ($_SESSION[$id] > 0) {
348                            $_SESSION[$id]--;
349                        }
350                        break;
351                    case 0:
352                        $_SESSION[$id] = 0;
353                        break;
354                    }
355                    echo $Embed->getItemCode($_SESSION[$id]);
356                } catch (AlbumEmbed_Exception $E) {
357                    echo '<p>' . $E->getMessage() . '</p>';
358                }
359            }
360        }
361    }
362
363    AlbumEmbed::main();
364
365?>
Note: See TracBrowser for help on using the browser.