As we have seen in the previous post (Your own cakephp file-browser for ckeditor: part 3 – youtube videos), it’s not hard to implement a search/browser of external data sources, with the ability to embed the desired formatted media in ckeditor.
Here’s a similar approach, interacting with Flickr’s API, with a catch.
The ingredients are almost the same of a popular article by Johnatant Snook on Site Point.
Drop the phpFlickr class in the vendor folder (i used version 2.3.1).
Get the FlickrComponent – a bridge to the phpFlick class, that loads it as a cake component – and the chasm between cakephp and the Flikr Api is crossed.
It’s all we need to populate our popup browser, by querying flickr.
We want to look for pohots and photosets – se the user can embed a single image or a slideshow. The catch is, there is no way to directly look for photosets.
Se, we look for photos, and optionally get the photosets it belongs to, with a second ajax action.
The other thing to consider is, the component itself is heavy and adds an unnecessary overhead in other “browsers”.
So, this time we create a new controller (AssetsFlickrController) that extends owr AssetController, and it’s used only for the flickr borwser popup.
Here, we implement two actions: the main index (with search and pagination) and an ajax action to get the selected picture and her related photosets.
The first method:
- <?php
- function admin_flickrbrowser($opener_instance, $page = 1, $per_page = 10, $id = null) {
- $this->_clean_params();
- // get the query parameters
- if (isset($this->data['Asset']['keyword']) && $this->data['Asset']['keyword'] != '') $keyword = $this->data['Asset']['keyword']; else $keyword = 'volontariato';
- if (isset($this->data['Asset']['author']) && $this->data['Asset']['author'] != '') $author = $this->data['Asset']['author'];
- }
- $username = $this->flickr->people_findByUsername($author);
- $photosets = $this->flickr->photosets_getList($username['id']);
- $this->set('photosets', $photosets['photoset']);
- } else
- 'text' => $keyword,
- 'page' => $page,
- 'per_page' => $per_page,
- 'sort' => 'interestingness-desc',
- 'extras' => 'license,date_upload,owner_name,icon_server,original_format,tags,o_dims,views,media,path_alias'
- ));
- }
- if($page == 1) $this->Session->write('total_pages', $thumbs['pages']);
- } else {
- $this->Session->write('total_pages', 1);
- }
- if($page < $this->Session->read('total_pages')) {
- $next_index = $page + 1;
- $opener_instance,
- $next_index,
- $per_page
- );
- $this->set('next_url', $url);
- }
- if($page > 1) {
- $previous_index = $page - 1;
- $opener_instance,
- $previous_index,
- $per_page
- );
- $this->set('previous_url', $url);
- }
- $this->set('opener_instance', $opener_instance);
- $this->render('admin_flickrbrowser', 'basic');
- }
- }
- ?>
As you see, the action gets the search parameters (form the popup’s form), and then performs the search -by author or keyword.
If the search was by username, we ask Flickr for author details, and then get his photosets with another query to flicker, using the user id found in the previous query:
$username = $this->flickr->people_findByUsername($author); $photosets = $this->flickr->photosets_getList($username['id']);
If the search is by keywords, we ask flicker for related pictures (by name, tag..) and get some extra info on the picture. (see Flicker API for more details)
$thumbs = $this->flickr->photos_search(array( 'text' => $keyword, 'page' => $page, 'per_page' => $per_page, 'sort' => 'interestingness-desc', 'extras' => 'license,date_upload,owner_name,icon_server,original_format,tags,o_dims,views,media,path_alias' ));
Then we set the variables for the view and handle “pagination” (using the flickr->photo_search provided parameters, page and per_page).
In the (popup) view, we list the paginated pictures found (or user’s photosets).
We use the phpFlickr methods to show thumbnails and build the photo url:
- <?php
- echo $javascript->link('prototype', false);
- echo $javascript->link('src/scriptaculous.js?load=effects,controls', false);
- ?>
- <script type="text/javascript">
- <!--
- function InsertHTML(passed)
- {
- var oEditor = opener.CKEDITOR.instances.<?php echo $opener_instance ?>;
- // Check the active editing mode.
- if ( oEditor.mode == 'wysiwyg' )
- {
- // Insert the desired HTML.
- oEditor.insertHtml( passed ) ;
- }
- else
- alert('<?php echo __('You must be on WYSIWYG mode!', true); ?>') ;
- window.close();
- }
- function hide(id) {
- document.getElementById(id).style.display = 'none';
- }
- -->
- </script>
- <div class="pannello">
- <h2><?php __('Photos and slideshow from Flickr');?></h2>
- <div class="art-Block">
- <p>
- <?php
- echo __('Search Flickr Photos or photosets by user');
- ?>
- </p>
- <?php echo $form->create('Asset',
- , 'type' => 'post'));?>
- <table border="0" cellpadding="10">
- <tbody>
- <tr>
- <td>
- <?php echo $html->image('social_me/big/flickr.png', array('align' => 'absmiddle', 'hspace' => '2'));; ?>
- </td>
- <td valign="middle">
- <?php
- ?>
- </td>
- <td valign="middle">
- <?php __('OR'); ?>
- </td>
- <td valign="middle">
- <?php
- echo $form->input('author', array('class' => 'size120', 'label' => __('Author / User Name',true) ));
- ?>
- </td>
- </tr>
- </tbody>
- </table>
- <?php
- <?php echo $form->end(); ?>
- </div>
- <div style="clear:both"></div>
- <?php $i=0; ?>
- <h2><?php
- </h2>
- <table cellpadding="0" cellspacing="0">
- <?php
- foreach($thumbs['photo'] as $item): ?>
- <?php
- ?>
- <tr>
- <td>
- <?php
- //
- // AJAX ACTION
- //
- echo $ajax->link(
- $html->image($flickr->buildPhotoURL($item, "small")),
- null,
- 'update' => 'show_actions_'. ++$i,
- 'indicator' => 'loading_'.$i
- ),
- null,
- false); ?>
- </td>
- <td>
- <h4><?php echo $item['title']?></h4>
- <div><strong><?php echo __('tags: ', true)?></strong> <?php echo $item['tags']; ?></div>
- <div><strong><?php echo __('views: ', true)?></strong> <?php echo $item['views']; ?></div>
- <div><strong><?php echo __('owner name: ', true)?></strong> <?php echo $item['ownername'];
- ?></div>
- <div id="loading_<?php echo $i; ?>" class="loading" style="display: none;">><?php echo $html->image('loading.gif'); ?></div>
- <div id="show_actions_<?php echo $i; ?>">
- </div>
- </td>
- </tr>
- <?php endforeach; ?>
- </table>
- <h2><?php
- </h2>
- <?php endif;
- ?>
- <table cellpadding="0" cellspacing="0">
- <?php
- foreach($photosets as $item): ?>
- <?php
- ?>
- <tr>
- <td>
- <?php
- $main_image = $flickr->photos_getInfo($item['primary']);
- ?>
- <?php echo $ajax->link(
- $html->image($flickr->buildPhotoURL($main_image, "small")),
- null,
- 'escape' => false,
- 'update' => 'show_actions_'. ++$i,
- 'indicator' => 'loading_'.$i
- ),
- null,
- false); ?>
- </td>
- <td>
- <h4><?php echo $item['title']?></h4>
- <div><strong><?php echo __('description: ', true)?></strong> <?php echo $item['description']; ?></div>
- <div><strong><?php echo $item['photos']; ?> </strong><?php echo __('photos', true)?> </div>
- <div><strong><?php echo $item['videos'];?> </strong><?php echo __('video', true)?></div>
- <div id="loading_<?php echo $i; ?>" class="loading" style="display: none;">><?php echo $html->image('loading.gif'); ?></div>
- <div id="show_actions_<?php echo $i; ?>">
- </div>
- </td>
- </tr>
- <?php endforeach; ?>
- </table>
- <?php endif; ?>
- </div>
If an user / author is searched, the html to embed the listed photosets is generated, like it was for the single pictures (see a previous post)
If the user is looking for photos by keyword, a link to the ajax admin_flickrGetDetails action is rendered.
Here is the full controller:
- <?php
- App::import('Sanitize');
- App::import('Controller', 'Assets');
- class AssetsFlickrController extends AssetsController {
- var $name = 'Assets';
- "Utility", "Media.Medium", "Number"); //"ExtendedForm"
- function admin_flickrbrowser($opener_instance, $page = 1, $per_page = 10, $id = null) {
- $this->_clean_params();
- // get the query parameters
- if (isset($this->data['Asset']['keyword']) && $this->data['Asset']['keyword'] != '') $keyword = $this->data['Asset']['keyword']; else $keyword = 'volontariato';
- if (isset($this->data['Asset']['author']) && $this->data['Asset']['author'] != '') $author = $this->data['Asset']['author'];
- }
- $username = $this->flickr->people_findByUsername($author);
- $photosets = $this->flickr->photosets_getList($username['id']);
- $this->set('photosets', $photosets['photoset']);
- } else
- 'text' => $keyword,
- 'page' => $page,
- 'per_page' => $per_page,
- 'sort' => 'interestingness-desc',
- 'extras' => 'license,date_upload,owner_name,icon_server,original_format,tags,o_dims,views,media,path_alias'
- ));
- }
- if($page == 1) $this->Session->write('total_pages', $thumbs['pages']);
- } else {
- $this->Session->write('total_pages', 1);
- }
- if($page < $this->Session->read('total_pages')) {
- $next_index = $page + 1;
- $opener_instance,
- $next_index,
- $per_page
- );
- $this->set('next_url', $url);
- }
- if($page > 1) {
- $previous_index = $page - 1;
- $opener_instance,
- $previous_index,
- $per_page
- );
- $this->set('previous_url', $url);
- }
- $this->set('opener_instance', $opener_instance);
- $this->render('admin_flickrbrowser', 'basic');
- }
- function admin_flickrGetDetails($photo_id, $title = 'photo from flickr') {
- $i = 0;
- $this->autoRender = false;
- $this->layout = 'ajax';
- $photo = $this->flickr->photos_getInfo($photo_id);
- $this->set('photo', $photo);
- $this->set('description', $title);
- $context = $this->flickr->photos_getAllContexts($photo_id);
- $this->set('context', $context);
- foreach($context['set'] as $photoset) {
- $set[] = $this->flickr->photosets_getInfo($photoset['id']);
- $main = $this->flickr->photos_getInfo($set[$i]['primary']);
- $set[$i]['primary'] = $main;
- $i++;
- }
- $this->set('set', $set);
- }
- $this->render('photo_context');
- }
- }
- ?>
So, with admin_flickrGetDetails we get the infos about the pictures, and related photosets – so we can indirectly look for photosets.
Last, here is the elemenet rendered by this action.
- <div style="display:block;" id="popupdiv">
- <div style="clear:both; padding:20px; background-color:white; border-style:solid; border-color:silver">
- <a href="javascript:hide('popupdiv')">
- <?php echo $html->image('icons/delete.png', array('align' => 'right', 'alt' => __('close',true), 'title' => __('close',true) )); ?>
- </a>
- <h4><?php __('Embed this image only'); ?></h4>
- <?php
- // generated HTML to be embedded in CKeditor
- $insert_left =
- $html->div('imageleft',
- "<p>".
- $html->link(
- $html->image($flickr->buildPhotoURL($photo, "small"),
- 'alt' => $photo['title'],
- 'title' => $photo['title'],
- )
- ),
- $photo['urls']['url'][0]['_content'],
- //$flickr->buildPhotoURL($photo, "original"),
- )
- . "</p><p><em>".$photo['title']."</em></p>",null,false). ' '
- ;
- $insert_right =
- $html->div('imageright',
- "<p>".
- $html->link(
- $html->image($flickr->buildPhotoURL($photo, "small"),
- 'alt' => $photo['title'],
- 'title' => $photo['title'],
- )
- ),
- $photo['urls']['url'][0]['_content'],//$flickr->buildPhotoURL($photo, "original"),
- )."</p><p><em>".$photo['title']."</em></p>",null,false). ' '
- ;
- $insert_center =
- $html->div('imagecenter',
- "<p>".
- $html->link(
- $html->image($flickr->buildPhotoURL($photo, "medium"),
- 'alt' => $photo['title'],
- 'title' => $photo['title'],
- )
- ),
- $photo['urls']['url'][0]['_content'],//$flickr->buildPhotoURL($photo, "original"),
- )."</p><p><em>".$photo['title']."</em></p>",null,false). ' '
- ;
- echo $html->link($html->image('icons_big/Image_Left.png',
- array('alt' => __('embed image', true), 'title' => __('embed image, align left', true), 'border' => 0, 'align' => 'absmiddle')),
- 'javascript:InsertHTML(\''. $insert_left .'\');',
- 'escape' => false,
- ),
- null, false
- );
- echo ' ';
- echo $html->link($html->image('icons_big/Image_Center.png',
- array('alt' => __('embed image', true), 'title' => __('embed image, big, center', true), 'border' => 0, 'align' => 'absmiddle')),
- 'javascript:InsertHTML(\''. $insert_center .'\');',
- ),
- null, false
- );
- echo ' ';
- echo $html->link($html->image('icons_big/Image_Right.png',
- array('alt' => __('embed image',true), 'title' => __('embed image, align right', true), 'border' => 0, 'align' => 'absmiddle')),
- 'javascript:InsertHTML(\''. $insert_right .'\');',
- ),
- null, false
- );
- ?>
- </div>
- <div style="clear:both; padding:20px; background-color:white; border-style:solid; border-color:silver">
- <h4><?php __('Or Embed Photosets'); ?></h4>
- <?php foreach($set as $thisset): ?>
- <?php
- ?>
- <div style="clear:both; padding:10px; border-style:dotted; border-color:silver">
- <h5><?php
- echo $html->image($flickr->buildPhotoURL($thisset['primary'], "thumbnail")
- ?>
- <?php echo $thisset['title']; ?></h5>
- <p>
- <?php echo $thisset['description']; ?>
- </p>
- <div style="clear:both">
- <?php
- $slideshow = '<object width="700" height="525"> <param name="flashvars" value="offsite=true&lang=it-it&page_show_url=%2Fphotos%2F'.$thisset['owner'].'%2Fsets%2F'.$thisset['id'].'%2Fshow%2F&page_show_back_url=%2Fphotos%2F'.$thisset['owner'].'%2Fsets%2F'.$thisset['id'].'%2F&set_id='.$thisset['id'].'&jump_to="></param> <param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowFullScreen="true" flashvars="offsite=true&lang=it-it&page_show_url=%2Fphotos%2F'.$thisset['owner'].'%2Fsets%2F'.$thisset['id'].'%2Fshow%2F&page_show_back_url=%2Fphotos%2F'.$thisset['owner'].'%2Fsets%2F'.$thisset['id'].'%2F&set_id='.$thisset['id'].'&jump_to=" width="700" height="525"></embed></object>';
- echo $html->link($html->image('social_me/medium/flickr.png',
- array('alt' => __('embed slideshow',true), 'title' => __('embed slideshow of this photoset', true), 'border' => 0, 'align' => 'absmiddle'))
- . ' ' . __('embed slideshow of this photoset', true),
- "javascript:InsertHTML('". $slideshow ."');",
- ),
- null, false
- );
- ?>
- </div>
- </div>
- <?php endforeach; ?>
- </div>
- <?php endif; ?>
- <p><?php echo __('Sorry..'); ?></p>
- <h4><?php echo __('This picture is not included in any photoset'); ?></h4>
- <?php endif; ?>
- </div>
It generates the needed html and shows the options to embed it in owr ckeditor instance (that called the popup) the single picture – like we did for owr uploaded images, big centered or medium right or left, with links to the original picture. This time, on Flickr.
Or, if available, a list of photosets containing the selected pictures, and the options to embed the needed html to show a slideshow of the photoset
Here we are. This is the end of this 4 part serie.
It was not the simplest thing in the world, but -using cakephp- was easy, wasn’t it?