Removed double <div> from Picasa2 album render
[tip.git] / Type / module / content / picasa2.php
blob2e96d4c9760652985be21b97aac9346f3dbfad60
1 <?php
2 /* vim: set expandtab shiftwidth=4 softtabstop=4 tabstop=4 foldmethod=marker: */
4 /**
5 * TIP_Picasa2 photo access
7 * LICENSE: This source file is subject to the New BSD license that is
8 * available through the world-wide-web at the following URI:
9 * http://www.opensource.org/licenses/bsd-license.php
10 * If you did not receive a copy of the New BSD License and are unable to
11 * obtain it through the web, please send a note to license@php.net so we
12 * can mail you a copy immediately.
14 * @author Nicola Fontana <ntd@entidi.it>
15 * @copyright Copyright &copy; 2010 Nicola Fontana
16 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
17 * @package TIP
18 * @since 0.3.4
21 /**
22 * A content module to access picasa version 2 photo throught its album feed
24 * A TIP_Content implementation that sets a default data engine
25 * capable to directly parse picasa album feed (version 2) to get
26 * metadata of photos.
28 * To be able to use this module, you should configure a picasa2
29 * module in your configuration options and feed it with the URI
30 * of the feed of a picasa album:
32 * <code>
33 * $cfg = array(
34 * ...
35 * 'picture' => array(
36 * 'type' => array('module', 'content', 'picasa2'),
37 * 'data' => 'http://picasaweb.google.com/data/feed/base/user/.../albumid/...'
38 * )
39 * ...
40 * );
41 * </code>
43 * The TIP_Picasa2 access to the feed is read-only but you need
44 * to fulfill the PicasaWeb Terms of Service in order to be allowed
45 * to access the feed:
47 * http://code.google.com/apis/picasaweb/terms.html
49 * After configuring it, you can use your newly "picture" module in
50 * the same way a common TIP_Content module is used.
52 * To be able to access the feed, TIP_Picasa2 considers any
53 * <entry> in the feed as any SQL engine treats a row in a table.
54 * The field of this virtual row are mapped to a usable field id
55 * using the "fields_xpath" property of the TIP_XML engine. Here
56 * it is a (probably outdated) list of these virtual fields
57 * (together with the XPath used to map their value):
59 * - **id** ({{link[contains(@rel,"#canonical")]/@href}})
60 * - **title** ({{media:group/media:title[@type="plain"]}})
61 * - **description** ({{media:group/media:description[@type="plain"]}})
62 * - **imageurl** ({{media:group/media:content[@medium="image"]/@url}})
63 * - **thumbnail** ({{media:group/media:thumbnail[3]/@url}})
64 * - **thumbnail_width** ({{media:group/media:thumbnail[3]/@width}})
65 * - **thumbnail_height** ({{media:group/media:thumbnail[3]/@height}})
66 * - **date** ({{published}})
67 * - **author** ({{../author/name}})
68 * - **uploader** ({{media:group/media:credit}})
70 * Adding new field mapping is trivial: up to now it was added what
71 * I actually need.
73 * The above fields can be used in you templates just as every other
74 * field provided by the more usual TIP_Mysql engine. For instance,
75 * to get a list of the first 5 items, you can do something like this:
77 * <code>
78 * <ul class="picture">{picture.forSelect(LIMIT 5)}
79 * <li><a href="{imageurl}">
80 * <img src="{thumbnail}" width="{thumbnail_width}" height="{thumbnail_height}" alt="{description}" />
81 * </li>{}
82 * </ul>
83 * </code>
85 * Because TIP_Picasa2 accesses the underlying feed using the TIP_XML
86 * data engine there are some known restriction: for instance,
87 * you can't do a complex SQL query using the ORDER BY or GROUP BY
88 * clauses. Check the TIP_XML documentation to exactly know which
89 * queries can be executed.
91 * @package TIP
93 class TIP_Picasa2 extends TIP_Content
95 //{{{ Construction/destruction
97 static protected function checkOptions(&$options)
99 if (@is_string($options['data'])) {
100 $options['data'] = array('path' => $options['data']);
103 // The data path is a required option
104 if (!@is_array($options['data']) || !isset($options['data']['path'])) {
105 return false;
108 TIP::arrayDefault($options, 'id_type', 'string');
109 TIP::arrayDefault($options['data'], 'data_engine', array(
110 'id' => 'picasa2',
111 'type' => array('data_engine', 'xml'),
112 'fields_xpath' => array(
113 'id' => 'link[contains(@rel,"#canonical")]/@href',
114 'title' => 'media:group/media:title[@type="plain"]',
115 'description' => 'media:group/media:description[@type="plain"]',
116 'imageurl' => 'media:group/media:content[@medium="image"]/@url',
117 'thumbnail' => 'media:group/media:thumbnail[3]/@url',
118 'thumbnail_width' => 'media:group/media:thumbnail[3]/@width',
119 'thumbnail_height' => 'media:group/media:thumbnail[3]/@height',
120 'date' => 'published',
121 'author' => '../author/name',
122 'uploader' => 'media:group/media:credit'
123 )));
125 return parent::checkOptions($options);
129 * Constructor
131 * Initializes a TIP_Picasa2 instance.
133 * @param array $options Properties values
135 protected function __construct($options)
137 parent::__construct($options);
140 //}}}
141 //{{{ Methods
144 * Get the html code for a PicasaWeb picture
146 * Renders the provided PicasaWeb URI (in the canonical form,
147 * usually something like http://picasaweb.google.com/lh/photo/...)
148 * to the proper <a ...><img ... /></a> element.
150 * This method starts (and ends) a view to find the row, so any
151 * further request is cached.
153 * @param string $id The PicasaWeb URI of the photo
154 * @return string|false The string to render or false on errors
156 public function toHtml($id)
158 if (is_null($view =& $this->startDataView($this->getData()->rowFilter($id)))) {
159 TIP::notifyError('select');
160 return false;
163 $rows =& $view->getProperty('rows');
164 if (!@array_key_exists($id, $rows))
165 return false;
167 return self::_renderRow($rows[$id], array('class' => 'picasa2'));
171 * Get the html code for the whole PicasaWeb album
173 * Renders all the photo included by this album.
175 * @return string|false The string to render or false on errors
177 public function toHtmlAlbum()
179 static $cnt = 1;
181 if (is_null($view =& $this->startDataView())) {
182 TIP::notifyError('select');
183 return false;
186 $rows =& $view->getProperty('rows');
187 $output = '';
188 $max_width = 0;
189 $max_height = 0;
190 $options = array(
191 'max-width' => &$max_width,
192 'max-height' => &$max_height
195 foreach ($rows as $row) {
196 $output .= ' <li>' . self::_renderRow($row, $options) . '</li>';
199 if (empty($output))
200 return false;
202 $id = 'Album' . $cnt;
203 ++$cnt;
205 $output = <<<EOT
206 <div class="caption" style="float: right">
207 <ul id="$id">
208 $output
209 </ul>
210 <p class="caption-title"><a id="$id-prev" href="#">« PRECEDENTE</a> <a id="$id-next" href="#">SEGUENTE »</a></p>
211 </div>
212 <script type="text/javascript">
213 jQuery(function() {
214 jQuery('#$id').ulslide({
215 width: $max_width,
216 height: $max_height,
217 bprev: '#$id-prev',
218 bnext: '#$id-next',
219 axis: 'x'
222 </script>
223 EOT;
225 return $output;
228 static private function _renderRow($row, $options = null)
230 $id = TIP::toHtml($row['id']);
231 $description = TIP::toHtml($row['description']);
232 $src = TIP::toHtml($row['thumbnail']);
233 $width = (int) $row['thumbnail_width'];
234 $height = (int) $row['thumbnail_height'];
236 $attrs = 'href="' . $id . '"';
237 empty($description) || $attrs .= ' title="' . $description . '"';
238 isset($options['class']) && $attrs .= ' class="' . $options['class'] . '"';
240 if (isset($options['max-width']) && $width > $options['max-width'])
241 $options['max-width'] = $width;
242 if (isset($options['max-height']) && $height > $options['max-height'])
243 $options['max-height'] = $height;
245 return "<a $attrs><img src=\"$src\" width=\"$width\" height=\"$height\" alt=\"$description\" /></a>\n";
248 //}}}