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_Search_Tags:: class provides logic for dealing with tag searching.
  4:  *
  5:  * Copyright 2007-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (GPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/gpl.
  9:  *
 10:  * @author  Michael J. Rubinsky <mrubinsk@horde.org>
 11:  * @category Horde
 12:  * @license  http://www.horde.org/licenses/gpl GPL
 13:  * @package  Ansel
 14:  */
 15: class Ansel_Search_Tag
 16: {
 17:     /**
 18:      * Array of tag_name => tag_id hashes for the current search.
 19:      * Tags are always added to the search by name and stored by name=>id.
 20:      *
 21:      * @var array
 22:      */
 23:     protected $_tags = array();
 24: 
 25:     /**
 26:      * Total count of all resources that match (both Galleries and Images).
 27:      *
 28:      * @var integer
 29:      */
 30:     protected $_totalCount = null;
 31: 
 32:     /**
 33:      * The user whose resources we are searching.
 34:      *
 35:      * @var string
 36:      */
 37:     protected $_owner = '';
 38: 
 39:     /**
 40:      * Dirty flag
 41:      *
 42:      * @var boolean
 43:      */
 44:     protected $_dirty = false;
 45: 
 46:     /**
 47:      * Results cache. Holds the results of the current search.
 48:      *
 49:      * @var array
 50:      */
 51:     protected $_results = array();
 52: 
 53:     /**
 54:      * The Ansel_Tagger object.
 55:      *
 56:      * @var Ansel_Tagger
 57:      */
 58:     protected $_tagger;
 59: 
 60:     /**
 61:      * Constructor
 62:      *
 63:      * @param array $tags    An array of tag names to match. If null is passed
 64:      *                       then the tags will be loaded from the session.
 65:      * @param string $owner  Restrict search to resources owned by specified
 66:      *                       owner.
 67:      *
 68:      * @return Ansel_Search_Tag
 69:      */
 70:     public function __construct(Ansel_Tagger $tagger, $tags = null, $owner = null)
 71:     {
 72:         $this->_tagger = $tagger;
 73:         if (!empty($tags)) {
 74:             $this->_tags = $this->_tagger->getTagIds($tags);
 75:         } else {
 76:             $this->_tags = $GLOBALS['session']->get('ansel', 'tags_search', Horde_Session::TYPE_ARRAY);
 77:         }
 78: 
 79:         $this->_owner = $owner;
 80: 
 81:     }
 82: 
 83:     /**
 84:      * Save the current search to the session
 85:      *
 86:      */
 87:     public function save()
 88:     {
 89:         $GLOBALS['session']->set('ansel', 'tags_search', $this->_tags);
 90:         $this->_dirty = false;
 91:     }
 92: 
 93:     /**
 94:      * Fetch the matching resources that should appear on the current page
 95:      *
 96:      * @return Array of Ansel_Images and Ansel_Galleries
 97:      */
 98:     public function getSlice($page, $perpage)
 99:     {
100:         global $conf, $registry;
101: 
102:         /* Refresh the search */
103:         $this->runSearch();
104:         $totals = $this->count();
105: 
106:         /* First, the galleries */
107:         $gstart = $page * $perpage;
108:         $gresults = array_slice($this->_results['galleries'], $gstart, $perpage);
109: 
110:         /* Instantiate the Gallery objects */
111:         $galleries = array();
112:         foreach ($gresults as $gallery) {
113:             try {
114:                 $galleries[] = $GLOBALS['injector']->getInstance('Ansel_Storage')->getGallery($gallery);
115:             } catch (Exception $e) {
116:                 Horde::logMessage('Gallery Not Found: ' . $gallery, 'ERR');
117:             }
118:         }
119: 
120:         /* Do we need to get images? */
121:         $istart = max(0, $page * $perpage - $totals['galleries']);
122:         $count = $perpage - count($galleries);
123:         if ($count > 0) {
124:             $iresults = array_slice($this->_results['images'], $istart, $count);
125:             try {
126:                 $images = count($iresults) ? array_values($GLOBALS['injector']->getInstance('Ansel_Storage')->getImages(array('ids' => $iresults))) : array();
127:             } catch (Horde_Exception_NotFound $e) {
128:                 throw new Ansel_Exception($e);
129:             }
130:             if (($conf['comments']['allow'] == 'all' || ($conf['comments']['allow'] == 'authenticated' && $GLOBALS['registry']->getAuth())) &&
131:                 $registry->hasMethod('forums/numMessagesBatch')) {
132: 
133:                 $ids = array_keys($images);
134:                 try {
135:                     $ccounts = $GLOBALS['registry']->forums->numMessagesBatch($ids, 'ansel');
136:                     foreach ($images as $image) {
137:                         $image->commentCount = (!empty($ccounts[$image->id]) ? $ccounts[$image->id] : 0);
138:                     }
139:                 } catch (Horde_Exception $e) {}
140:             }
141:         } else {
142:             $images = array();
143:         }
144: 
145:         return array_merge($galleries, $images);
146:     }
147: 
148:     /**
149:      * Add a tag to the cumulative tag search
150:      *
151:      * @param string $tag  The tag name to add.
152:      *
153:      * @return void
154:      */
155:     public function addTag($tag)
156:     {
157:         $tag_id = (int)current($this->_tagger->getTagIds($tag));
158:         if (array_search($tag_id, $this->_tags) === false) {
159:             $this->_tags[$tag] = $tag_id;
160:             $this->_dirty = true;
161:         }
162:     }
163: 
164:     /**
165:      * Remove a tag from the cumulative search
166:      *
167:      * @param string $tag  The tag name to remove.
168:      *
169:      * @return void
170:      */
171:     public function removeTag($tag)
172:     {
173:         if (!empty($this->_tags[$tag])) {
174:             unset($this->_tags[$tag]);
175:             $this->_dirty = true;
176:         }
177:     }
178: 
179:     /**
180:      * Get the list of currently choosen tags
181:      *
182:      * @return array  An array of selected tag_name => tag_id hashes.
183:      */
184:     public function getTags()
185:     {
186:         return $this->_tags;
187:     }
188: 
189:     /**
190:      * Get breadcrumb style navigation html for choosen tags
191:      *
192:      * @TODO: Remove the html generation to the view class
193:      *
194:      * @return string  The html representing the tag trail for browsing tags.
195:      */
196:     public function getTagTrail()
197:     {
198:         global $registry;
199: 
200:         $html = '<ul class="tag-list">';
201: 
202:         /* Use the local cache to preserve the order */
203:         $count = 0;
204:         foreach ($this->_tags as $tagname => $tagid) {
205:             $remove_url = Horde::url('view.php', true)->add(
206:                     array('view' => 'Results',
207:                           'tag' => $tagname,
208:                           'actionID' => 'remove'));
209:             if (!empty($this->_owner)) {
210:                 $remove_url->add('owner', $this->_owner);
211:             }
212:             $delete_label = sprintf(_("Remove %s from search"), htmlspecialchars($tagname));
213:             $html .= '<li>' . htmlspecialchars($tagname) . $remove_url->link(array('title' => $delete_label)) . Horde::img('delete-small.png', $delete_label) . '</a></li>';
214:         }
215: 
216:         return $html . '</ul>';
217:     }
218: 
219:     /**
220:      * Get the total number of tags included in this search.
221:      *
222:      * @return integer  The number of tags used in the current search.
223:      */
224:     public function tagCount()
225:     {
226:         return count($this->_tags);
227:     }
228: 
229:     /**
230:      * Get the total number of resources that match.
231:      *
232:      * @return array  Hash containing totals for both 'galleries' and 'images'.
233:      */
234:     public function count()
235:     {
236:         if (!is_array($this->_tags) || !count($this->_tags)) {
237:             return 0;
238:         }
239: 
240:         $count = array('galleries' => count($this->_results['galleries']), 'images' => count($this->_results['images']));
241:         $this->_totalCount = $count;
242: 
243:         return $count;
244:     }
245: 
246:     /**
247:      * Get a list of tags related to this search
248:      *
249:      * @return array An array  tag_id => {tag_name, total}
250:      */
251:     public function getRelatedTags()
252:     {
253:         $tags = $this->_tagger->browseTags($this->getTags(), $this->_owner);
254:         $search = new Ansel_Search_Tag($this->_tagger, null, $this->_owner);
255:         $results = array();
256:         foreach ($tags as $id => $tag) {
257:             $search->addTag($tag);
258:             $search->runSearch();
259:             $count = $search->count();
260:             if ($count['images'] + $count['galleries'] > 0) {
261:                 $results[$id] = array('tag_name' => $tag, 'total' => $count['images'] + $count['galleries']);
262:             }
263:             $search->removeTag($tag);
264:         }
265: 
266:         /* Get the results sorted by available totals for this user */
267:         uasort($results, array($this, '_sortTagInfo'));
268:         return $results;
269:     }
270: 
271:     /**
272:      * Perform, and cache the search.
273:      *
274:      */
275:     public function runSearch()
276:     {
277:         if (!empty($this->_owner)) {
278:             $filter = array('user' => $this->_owner);
279:         } else {
280:             $filter = array();
281:         }
282:         if (empty($this->_results) || $this->_dirty) {
283:             $this->_results = $this->_tagger
284:                     ->search($this->_tags, $filter);
285:         }
286:     }
287: 
288:     /**
289:      * Clears the session cache of tags currently included in the search.
290:      */
291:     static public function clearSearch()
292:     {
293:         $GLOBALS['session']->remove('ansel', 'tags_search');
294:     }
295: 
296:     /**
297:      * Helper for uasort.  Sorts the results by count.
298:      *
299:      */
300:     private function _sortTagInfo($a, $b)
301:     {
302:         return $a['total']  <  $b['total'];
303:     }
304: 
305: }
306: 
API documentation generated by ApiGen