Overview

Packages

  • Ansel
  • None

Classes

  • Ansel
  • Ansel_Ajax_Application
  • Ansel_Ajax_Imple_EditCaption
  • Ansel_Ajax_Imple_EditFaces
  • Ansel_Ajax_Imple_EditGalleryFaces
  • Ansel_Ajax_Imple_Embed
  • Ansel_Ajax_Imple_GallerySlugCheck
  • Ansel_Ajax_Imple_ImageSaveGeotag
  • Ansel_Ajax_Imple_LocationAutoCompleter
  • Ansel_Ajax_Imple_MapLayerSelect
  • Ansel_Ajax_Imple_TagActions
  • Ansel_Ajax_Imple_ToggleGalleryActions
  • Ansel_Ajax_Imple_ToggleOtherGalleries
  • Ansel_Ajax_Imple_UploadNotification
  • Ansel_Api
  • Ansel_Exception
  • Ansel_Faces
  • Ansel_Faces_Base
  • Ansel_Faces_Facedetect
  • Ansel_Faces_User
  • Ansel_Factory_Faces
  • Ansel_Factory_Storage
  • Ansel_Factory_Styles
  • Ansel_Form_Ecard
  • Ansel_Form_Image
  • Ansel_Form_ImageDate
  • Ansel_Form_Upload
  • Ansel_Gallery
  • Ansel_Gallery_Decorator_Date
  • Ansel_GalleryMode_Base
  • Ansel_GalleryMode_Date
  • Ansel_GalleryMode_Normal
  • Ansel_Image
  • Ansel_ImageGenerator
  • Ansel_ImageGenerator_Mini
  • Ansel_ImageGenerator_PolaroidThumb
  • Ansel_ImageGenerator_PolaroidThumbStack
  • Ansel_ImageGenerator_RoundedThumb
  • Ansel_ImageGenerator_RoundedThumbStack
  • Ansel_ImageGenerator_Screen
  • Ansel_ImageGenerator_ShadowThumb
  • Ansel_ImageGenerator_ShadowThumbStack
  • Ansel_ImageGenerator_SquareThumb
  • Ansel_ImageGenerator_Thumb
  • Ansel_LoginTasks_SystemTask_Upgrade
  • Ansel_Report
  • Ansel_Report_letter
  • Ansel_Report_mail
  • Ansel_Report_tickets
  • Ansel_Search
  • Ansel_Search_exif
  • Ansel_Search_Tag
  • Ansel_Storage
  • Ansel_Style
  • Ansel_Tagger
  • Ansel_Test
  • Ansel_Tile_DateGallery
  • Ansel_Tile_Gallery
  • Ansel_Tile_Image
  • Ansel_View_Ansel
  • Ansel_View_Base
  • Ansel_View_EmbeddedRenderer_GalleryLink
  • Ansel_View_EmbeddedRenderer_Mini
  • Ansel_View_EmbeddedRenderer_Slideshow
  • Ansel_View_Gallery
  • Ansel_View_GalleryProperties
  • Ansel_View_GalleryRenderer_Base
  • Ansel_View_GalleryRenderer_Gallery
  • Ansel_View_GalleryRenderer_GalleryLightbox
  • Ansel_View_Image
  • Ansel_View_List
  • Ansel_View_Results
  • Ansel_View_Slideshow
  • Ansel_View_Upload
  • Ansel_Widget
  • Ansel_Widget_Actions
  • Ansel_Widget_Base
  • Ansel_Widget_GalleryFaces
  • Ansel_Widget_Geotag
  • Ansel_Widget_ImageFaces
  • Ansel_Widget_Links
  • Ansel_Widget_OtherGalleries
  • Ansel_Widget_OwnerFaces
  • Ansel_Widget_SimilarPhotos
  • Ansel_Widget_Tags
  • Ansel_XPPublisher
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Ansel_Widget_Geotag:: class to wrap the display of a Google map showing
  4:  * images with geolocation data.
  5:  *
  6:  * Copyright 2009-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * See the enclosed file COPYING for license information (GPL). If you
  9:  * did not receive this file, see http://www.horde.org/licenses/gpl.
 10:  *
 11:  * @TODO: Refactor the JS out to a seperate file, output needed values in the
 12:  *        GLOBAL Ansel javascript object. Rewrite for Horde_Map js.
 13:  *
 14:  * @author Michael J. Rubinsky <mrubinsk@horde.org>
 15:  * @package Ansel
 16:  */
 17: class Ansel_Widget_Geotag extends Ansel_Widget_Base
 18: {
 19:     /**
 20:      * List of views this widget supports
 21:      *
 22:      * @var array
 23:      */
 24:     protected $_supported_views = array(
 25:         'Image',
 26:         'Gallery');
 27: 
 28:     /**
 29:      * Default params
 30:      *
 31:      * @var array
 32:      */
 33:     protected $_params = array(
 34:         'default_zoom' => 15,
 35:         'max_auto_zoom' => 15);
 36: 
 37:     /**
 38:      * Const'r
 39:      *
 40:      * @param array $params
 41:      *
 42:      * @return Ansel_Widget_Geotag
 43:      */
 44:     public function __construct($params)
 45:     {
 46:         parent::__construct($params);
 47:         $this->_title = _("Location");
 48:     }
 49: 
 50:     /**
 51:      * Attach widget to supplied view.
 52:      *
 53:      * @param Ansel_View_Base $view
 54:      *
 55:      * @return boolean
 56:      */
 57:     public function attach(Ansel_View_Base $view)
 58:     {
 59:         if (empty($GLOBALS['conf']['maps']['driver'])) {
 60:             return false;
 61:         }
 62:         parent::attach($view);
 63:         return true;
 64:     }
 65: 
 66:     /**
 67:      * Build the HTML for the widget
 68:      *
 69:      * @return string
 70:      */
 71:     public function html()
 72:     {
 73:         $ansel_storage = $GLOBALS['injector']->getInstance('Ansel_Storage');
 74:         $geodata = $ansel_storage->getImagesGeodata($this->_params['images']);
 75:         $viewType = $this->_view->viewType();
 76: 
 77:         // Exit early?
 78:         if (count($geodata) == 0 && $viewType != 'Image') {
 79:             return '';
 80:         } elseif (count($geodata) == 0) {
 81:             $noGeotag = true;
 82:         }
 83: 
 84:         // Setup map and javascript includes
 85:         Ansel::initHordeMap($GLOBALS['conf']['maps']);
 86:         Horde::addScriptFile('popup.js', 'horde');
 87:         Horde::addScriptFile('widgets/geotag.js');
 88: 
 89:         // Values needed by map javascript
 90:         $url = Horde::url('map_edit.php', true);
 91:         $rtext = _("Relocate this image");
 92:         $dtext = _("Delete geotag");
 93:         $thisTitleText = _("This image");
 94:         $otherTitleText = _("Other images in this gallery");
 95:         $imple = $GLOBALS['injector']
 96:             ->getInstance('Horde_Core_Factory_Imple')
 97:             ->create(array('ansel', 'ImageSaveGeotag'));
 98:         $impleUrl = $imple->getUrl();
 99: 
100:         $permsEdit = (integer)$this->_view->gallery->hasPermission(
101:             $GLOBALS['registry']->getAuth(),
102:             Horde_Perms::EDIT);
103: 
104:         // URL for updating selected layer
105:         $imple =  $GLOBALS['injector']
106:             ->getInstance('Horde_Core_Factory_Imple')
107:             ->create(array('ansel', 'MapLayerSelect'));
108:         $layerImpleUrl = $imple->getUrl();
109: 
110:         // And the current defaultLayer, if any.
111:         $defaultLayer = $GLOBALS['prefs']->getValue('current_maplayer');
112: 
113:         // Add extra information to the JSON data to be sent:
114:         foreach ($geodata as $id => $data) {
115:             $geodata[$id]['icon'] = (string)Ansel::getImageUrl(
116:                 $geodata[$id]['image_id'],
117:                 'mini',
118:                 true);
119:             $geodata[$id]['markerOnly'] = ($viewType == 'Image');
120:             $geodata[$id]['link'] = (string)Ansel::getUrlFor(
121:                 'view',
122:                  array(
123:                      'view' => 'Image',
124:                      'gallery' => $this->_view->gallery->id,
125:                      'image' => $geodata[$id]['image_id']),
126:                 true);
127:         }
128: 
129:         // Start HTML building for widget
130:         $html = $this->_htmlBegin() . "\n";
131:         $content = '<div id="ansel_geo_widget">';
132: 
133:         // If this is an image view, get the other gallery images
134:         if ($viewType == 'Image') {
135:             $image_id = $this->_view->resource->id;
136:             $others = $this->_getGalleryImagesWithGeodata();
137:             foreach ($others as $id => $data) {
138:                 if ($id != $image_id) {
139:                     $others[$id]['icon'] = (string)Ansel::getImageUrl(
140:                         $others[$id]['image_id'],
141:                         'mini',
142:                         true);
143:                     $others[$id]['link'] = (string)Ansel::getUrlFor(
144:                             'view',
145:                             array(
146:                                 'view' => 'Image',
147:                                 'gallery' => $this->_view->gallery->id,
148:                                 'image' => $others[$id]['image_id']),
149:                             true);
150:                 } else {
151:                     unset($others[$id]);
152:                 }
153:             }
154:             $geodata = array_values(array_merge($geodata, $others));
155: 
156:             // If we have geo data, build dom structure for maps, otherwise
157:             // build HTML for "Add geodata" section.
158:             if (empty($noGeotag)) {
159:                 $content .= '<div id="ansel_map"></div>';
160:                 $content .= '<div class="ansel_geolocation">';
161:                 $content .= '<div id="ansel_locationtext"></div>';
162:                 $content .= '<div id="ansel_latlng"></div>';
163:                 $content .= '<div id="ansel_relocate"></div><div id="ansel_deleteGeotag"></div></div>';
164:                 $content .= '<div id="ansel_map_small"></div>';
165:             } elseif ($permsEdit) {
166:                 // Image view, but no geotags, provide ability to add it.
167:                 $addurl = Horde::url('map_edit.php')->add(
168:                     'image',
169:                     $this->_params['images'][0]);
170:                 $addLink = $addurl->link(
171:                     array('onclick' => Horde::popupJs(
172:                         Horde::url('map_edit.php'),
173:                         array('params' => array('image' => $this->_params['images'][0]), 'urlencode' => true, 'width' => '750', 'height' => '600'))
174:                     . 'return false;'));
175: 
176:                 $imgs = $ansel_storage
177:                     ->getRecentImagesGeodata($GLOBALS['registry']->getAuth());
178:                 if (count($imgs) > 0) {
179:                     $imgsrc = '<div class="ansel_location_sameas">';
180:                     foreach ($imgs as $id => $data) {
181:                         if (!empty($data['image_location'])) {
182:                             $title = $data['image_location'];
183:                         } else {
184:                             $title = $this->_point2Deg($data['image_latitude'], true)
185:                                 . ' '
186:                                 . $this->_point2Deg($data['image_longitude']);
187:                         }
188:                         $imgsrc .= $addurl->link(
189:                             array('
190:                                 title' => $title,
191:                                 'onclick' => "Ansel.widgets.geotag.setLocation(" . $image_id . ",'" . $data['image_latitude'] . "', '" . $data['image_longitude'] . "'); return false"
192:                             ))
193:                             . '<img src="' . Ansel::getImageUrl($id, 'mini', true) . '" alt="[image]" /></a>';
194:                     }
195:                     $imgsrc .= '</div>';
196:                     $content .= sprintf(_("No location data present. Place using %s map %s or click on image to place at the same location."), $addLink, '</a>') . $imgsrc;
197:                 } else {
198:                     $content .= sprintf(_("No location data present. You may add some %s."), $addLink . _("here") . '</a>');
199:                 }
200:             } else {
201:                 $content .= _("No location data present.");
202:             }
203: 
204:         } else {
205:             // Gallery view-------------
206:             $image_id = 0;
207:             $content .= '<div id="ansel_map"></div>'
208:                       . '<div id="ansel_locationtext" style="min-height: 20px;"></div>'
209:                       . '<div id="ansel_map_small"></div>';
210:         }
211:         $content .= '</div>';
212: 
213:         // Build the javascript to handle the map on the gallery/image views.
214:         $json = Horde_Serialize::serialize(array_values($geodata), Horde_Serialize::JSON);
215:         $html .= <<<EOT
216:         <script type="text/javascript">
217:         Ansel.widgets = Ansel.widgets || {};
218:         Ansel.widgets.geotag = new AnselGeoTagWidget(
219:             {$json},
220:             {
221:                 smallMap: 'ansel_map_small',
222:                 mainMap:  'ansel_map',
223:                 viewType: '{$viewType}',
224:                 relocateUrl: '{$url}',
225:                 relocateText: '{$rtext}',
226:                 markerLayerTitle: '{$thisTitleText}',
227:                 imageLayerTitle: '{$otherTitleText}',
228:                 defaultBaseLayer: '{$defaultLayer}',
229:                 deleteGeotagText: '{$dtext}',
230:                 hasEdit: {$permsEdit},
231:                 updateEndpoint: '{$impleUrl}',
232:                 layerUpdateEndpoint: '{$layerImpleUrl}',
233:                 geocoder: "{$GLOBALS['conf']['maps']['geocoder']}"
234:             }
235:         );
236: EOT;
237:         if (empty($noGeotag)) {
238:             $html .= "\n" . 'Event.observe(window, "load", function() { Ansel.widgets.geotag.doMap(); });' . "\n";
239:         }
240:         $html .= '</script>' . "\n";
241:         $html .= $content. $this->_htmlEnd();
242: 
243:         return $html;
244:     }
245: 
246:     /**
247:      *
248:      * @return array
249:      */
250:     protected function _getGalleryImagesWithGeodata()
251:     {
252:         return $GLOBALS['injector']
253:             ->getInstance('Ansel_Storage')
254:             ->getImagesGeodata(array(), $this->_view->gallery->id);
255:     }
256: 
257:     /**
258:      * Helper function for converting from decimal points to degrees lat/lng
259:      *
260:      * @param float   $value  The value
261:      * @param boolean $lat    Does this value represent a latitude?
262:      *
263:      * @return string  The textual representation in degrees.
264:      */
265:     protected function _point2Deg($value, $lat = false)
266:     {
267:         $letter = $lat ? ($value > 0 ? "N" : "S") : ($value > 0 ? "E" : "W");
268:         $value = abs($value);
269:         $deg = floor($value);
270:         $min = floor(($value - $deg) * 60);
271:         $sec = ($value - $deg - $min / 60) * 3600;
272:         return $deg . "&deg; " . $min . '\' ' . round($sec, 2) . '" ' . $letter;
273:     }
274: 
275: }
276: 
API documentation generated by ApiGen