1<?php
2
3/**
4 * Plugin facebookalbum: Displays Facebook photo albums.
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @version    1.0
8 * @date       April 2012
9 * @author     J. Drost-Tenfelde <info@drost-tenfelde.de>
10 *
11 * This plugin uses the Facebook SDK.
12 *
13 */
14
15// must be run within Dokuwiki
16if(!defined('DOKU_INC')) die();
17
18if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
19require_once(DOKU_PLUGIN.'syntax.php');
20
21// Syntax parameters
22define( "FB_ALBUM_APPLICATION_ID", "appid" );
23define( "FB_ALBUM_SECRET", "secret" );
24define( "FB_ALBUM_FAN_PAGE_ID", "fanpageid" );
25define( "FB_ALBUM_IGNORE", "ignore" );
26define( "FB_ALBUM_ORDER", "order" );
27
28define( "FB_ALBUM_TEMPLATE_ALBUM", "album_template" );
29define( "FB_ALBUM_TEMPLATE_PICTURE", "picture_template" );
30
31define( "FB_ALBUM_GET_PARAMETER_ACTION", "fbp_act" );
32define( "FB_ALBUM_GET_PARAMETER_ALBUM_ID", "fbp_aid" );
33
34// Template tags
35define( "FB_ALBUM_TAG_NAME", "{name}");
36define( "FB_ALBUM_TAG_URL", "{url}");
37define( "FB_ALBUM_TAG_IMAGE_URL", "{image_url}");
38define( "FB_ALBUM_TAG_BACK", "{back}");
39
40define( "FB_ALBUM_TAG_CAPTION", "{caption}");
41define( "FB_ALBUM_TAG_ALBUM_NAME", "{album_name}");
42define( "FB_ALBUM_TAG_IMAGE_SMALL_URL", "{image_small_url}");
43define( "FB_ALBUM_TAG_IMAGE_BIG_URL", "{image_large_url}");
44
45/**
46 * This plugin retrieves facebook photos and photo albums displays them in HTML.
47 *
48 * Usage: {{facebookalbum#appid=1234&secret=12345&fanpageid=12345}}
49 *
50 */
51class syntax_plugin_facebookalbum extends DokuWiki_Syntax_Plugin
52{
53    function getInfo() {
54      return array(
55        'author' => 'J. Drost-Tenfelde',
56        'email'  => 'info@drost-tenfelde.de',
57        'date'   => '2012-04-13',
58        'name'   => 'facebookalbum',
59        'desc'   => 'Displays Facebook photo albums',
60        'url'    => 'http://www.drost-tenfelde.de/?id=dokuwiki:plugins:facebookalbum',
61      );
62    }
63
64    // implement necessary Dokuwiki_Syntax_Plugin methods
65    function getType() { return 'substition'; }
66    function getSort() { return 42; }
67    function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{facebookalbum.*?\}\}',$mode,'plugin_facebookalbum'); }
68
69	/**
70	 * parse parameters from the {{facebookwall#...}} tag.
71	 * @return an array that will be passed to the renderer function
72	 */
73	function handle($match, $state, $pos, &$handler) {
74    // Get the syntax parameters
75    $match = substr($match, 16, -2);
76		parse_str($match, $params);
77
78		// App-Id
79    if ( !$params[FB_ALBUM_APPLICATION_ID] ) {
80      // Get the application-id from the configuration instead
81      $params[FB_ALBUM_APPLICATION_ID] = $this->getConf(FB_ALBUM_APPLICATION_ID);
82      // Make sure it was set
83      if ( !$params[FB_ALBUM_APPLICATION_ID] ) {
84        $this->error = $this->getLang('error_appid_not_set');
85      }
86    }
87
88    // Secret
89    if ( !$params[FB_ALBUM_SECRET] ) {
90      // Get the secret from the configuration instead
91      $params[FB_ALBUM_SECRET] = $this->getConf(FB_ALBUM_SECRET);
92      // Make sure it was set
93      if ( !$params[FB_ALBUM_SECRET] ) {
94        $this->error = $this->getLang('error_secret_not_set');
95      }
96    }
97
98    // Page-Id
99    if ( !$params[FB_ALBUM_FAN_PAGE_ID] ) {
100      // Get the page id from the configuration instead
101      $params[FB_ALBUM_FAN_PAGE_ID] = $this->getConf(FB_ALBUM_FAN_PAGE_ID);
102      // Make sure it was set
103      if ( !$params[FB_ALBUM_FAN_PAGE_ID] ) {
104        $this->error = $this->getLang('error_fanpageid_not_set');
105      }
106    }
107
108    // Ordering
109    if ( $params[FB_ALBUM_ORDER] != 'ASC' ) {
110      // Get the ordering from the configuration instead
111      $params[FB_ALBUM_ORDER] = $this->getConf(FB_ALBUM_ORDER);
112      // If not set, default to descending
113      if ( $params[FB_ALBUM_ORDER] != 'ASC' ) {
114        $params[FB_ALBUM_ORDER] = 'DESC';
115      }
116    }
117
118    // Get the ignore names of albums that are to be ignored
119    if ( !$params[FB_ALBUM_IGNORE] ) {
120      // Get the ignore names from the configuration instead
121      $params[FB_ALBUM_IGNORE] = $this->getConf(FB_ALBUM_IGNORE);
122    }
123    $ignore_names = strtolower( $params[FB_ALBUM_IGNORE] );
124    // Turn the names into an array
125    $params[FB_ALBUM_IGNORE] = explode("|", $ignore_names );
126
127		return $params;
128  }
129
130	/**
131	 * Retrieves the facebook events and parses them to HTML.
132	 */
133	function render($mode, &$renderer, $data) {
134    global $ID;
135    $info = $this->getInfo();
136
137    $content = '';
138
139		if ($mode == 'xhtml') {
140      // Catch errors
141      if ($this->error) {
142        $renderer->doc .= 'Error in Plugin '.$info['name'].': '.$this->error;
143        return;
144      }
145
146      //See if an action was provided
147      isset( $_REQUEST[FB_ALBUM_GET_PARAMETER_ACTION] ) ? $action = $_REQUEST[FB_ALBUM_GET_PARAMETER_ACTION] : $action = "";
148
149
150      if (!class_exists('Facebook')) {
151        include_once('facebook.php');
152      }
153      // Initialise Facebook
154      $facebook = new Facebook( array(
155        'appId'  => $data['appid'],
156        'secret' => $data['secret'],
157        'cookie' => true, // enable optional cookie support
158      ) );
159
160      // See which action is to be taken
161      if ( $action == '') {
162        // Query for the albums
163        $album_query = 'SELECT aid, cover_pid, name FROM album WHERE owner='.$data['fanpageid']. ' and photo_count > 0';
164        $album_query .= 'ORDER BY name '.$data[FB_ALBUM_ORDER];
165
166        // Query for the album covers
167        $cover_query = 'SELECT pid, src FROM photo where pid in (SELECT cover_pid from #album_query)';
168
169        //Combine the queries for speed
170        $queries = array( "album_query" => $album_query, "cover_query" => $cover_query );
171        // Set the parameters for the API
172        $param = array(
173          'method'    => 'fql.multiquery',
174          'queries'     => $queries,
175          'callback'  => ''
176        );
177
178        // Execute the queries
179        $results = $facebook->api($param);
180        $album_results = $results[0]['fql_result_set'];
181        $cover_results = $results[1]['fql_result_set'];
182
183        // Turn the covers into an array for quick refference
184        $covers = array();
185        foreach( $cover_results as $cover ) {
186          $covers[ $cover['pid'] ] = $cover['src'];
187        }
188
189        // Get the template for the albums
190        $album_template = $this->getConf(FB_ALBUM_TEMPLATE_ALBUM);
191
192        // Loop through the albums
193        foreach( $album_results as $keys => $values ) {
194          // Make sure the album name is not to be ignored
195          if ( in_array(strtolower($values['name']), $data[FB_ALBUM_IGNORE])) {
196            continue;
197          }
198
199          // Get the cover image
200          $album_cover = $covers[$values['cover_pid']];
201
202          // Assemble the url
203          $album_url = $_SERVER['REQUEST_URI']."&".FB_ALBUM_GET_PARAMETER_ACTION."=list_photos&".FB_ALBUM_GET_PARAMETER_ALBUM_ID."=".$values['aid'];
204
205          // Assemble the content of the album
206          $album_content = $album_template;
207          // Name
208          $album_content = str_replace(FB_ALBUM_TAG_NAME, $values['name'], $album_content);
209          // URL
210          $album_content = str_replace(FB_ALBUM_TAG_URL, $album_url, $album_content);
211          // Cover image
212          $album_content = str_replace(FB_ALBUM_TAG_IMAGE_URL, $album_cover, $album_content);
213
214          $content .= $album_content;
215        }
216      }
217      else if ( $action == 'list_photos' ) {
218
219        // Get the template for the albums
220        $photo_template = $this->getConf(FB_ALBUM_TEMPLATE_ALBUM);
221
222        // Add a "Back" link
223        $renderer->doc .= "<p>".html_wikilink($ID, $this->getLang('back_to_albums'))."</p>";
224
225        // Get the album name
226        $fql = "SELECT name FROM album WHERE aid='".$_REQUEST[FB_ALBUM_GET_PARAMETER_ALBUM_ID]."'";
227        // Set the parameters
228        $param = array(
229          'method'    => 'fql.query',
230          'query'     => $fql,
231          'callback'  => ''
232        );
233        // Execute the query
234        $fql_results = $facebook->api($param);
235        foreach( $fql_results as $keys => $values ) {
236          $album_name = $values['name'];
237          break;
238        }
239
240        // Get pictures within the album
241        $fql = "SELECT pid, src, src_small, src_big, caption FROM photo WHERE aid = '" . $_REQUEST[FB_ALBUM_GET_PARAMETER_ALBUM_ID] ."'  ORDER BY created DESC";
242        $param  =   array(
243          'method'    => 'fql.query',
244          'query'     => $fql,
245          'callback'  => ''
246        );
247        $fql_results = $facebook->api($param);
248
249        // Get the display template
250        $picture_template = $this->getConf(FB_ALBUM_TEMPLATE_PICTURE);
251
252        // Loop through the pictures
253        foreach( $fql_results as $keys => $values ) {
254          if( $values['caption'] == '' ){
255            $caption = "";
256          }
257          else {
258            $caption = $values['caption'];
259          }
260
261          $picture_content = $picture_template;
262          $picture_content = str_replace( FB_ALBUM_TAG_CAPTION, $caption, $picture_content);
263          $picture_content = str_replace( FB_ALBUM_TAG_ALBUM_NAME, album_name, $picture_content);
264          $picture_content = str_replace( FB_ALBUM_TAG_IMAGE_URL, $values['src'], $picture_content);
265          $picture_content = str_replace( FB_ALBUM_TAG_IMAGE_SMALL_URL, $values['src_small'], $picture_content);
266          $picture_content = str_replace( FB_ALBUM_TAG_IMAGE_BIG_URL, $values['src_big'], $picture_content);
267
268          $content .= $picture_content;
269        }
270      }
271
272      // Render the DokuWiki syntax
273      $renderer->doc .= p_render($mode, p_get_instructions( $content ), $info );
274      // Add a clearer
275      $renderer->doc .= "<div class=\"clearer\"></div>";
276
277			return true;
278		}
279		return false;
280	}
281}
282
283?>