1: <?php
2: /**
3: * Base class for the creation of various image views.
4: *
5: * New thumbnail generators can be dropped in and will be made available by
6: * Ansel providing:
7: *
8: * 1. The class name is as: Ansel_ImageGenerator_{type}Thumb and filename
9: * matches, i.e. {type}Thumb.php where {type} is the unique name for your
10: * thumbnail type.
11: *
12: * 2. Implements a _create() method that applies the effects to the image
13: * (see existing generators for how this works).
14: *
15: * 3. If a matching "stack" generator is desired, that should be named
16: * similarly: Ansel_ImageGenerator_{type}ThumbStack with matching filename:
17: * {type}ThumbStack.php
18: *
19: *
20: * Copyright 2007-2012 Horde LLC (http://www.horde.org/)
21: *
22: * See the enclosed file COPYING for license information (GPL). If you
23: * did not receive this file, see http://www.horde.org/licenses/gpl.
24: *
25: * @author Michael J. Rubinsky <mrubinsk@horde.org>
26: * @package Ansel
27: */
28: class Ansel_ImageGenerator
29: {
30: /**
31: * Ansel_Image object that this view is created from.
32: *
33: * @var Ansel_Image
34: */
35: protected $_image = null;
36:
37: /**
38: * Parameters for this view
39: *
40: * @var array
41: */
42: protected $_params = array();
43:
44: /**
45: * Image dimensions
46: *
47: * @var array
48: */
49: protected $_dimensions = array();
50:
51: /**
52: * Cache the style
53: *
54: * @var Ansel_Style
55: */
56: protected $_style;
57:
58: /**
59: * Array of required, supported features for this ImageGenerator to work
60: *
61: * @var array
62: */
63: public $need = array();
64:
65: /**
66: * Human readable title for this thumbnail style.
67: *
68: * @var string
69: */
70: public $title;
71:
72: /**
73: * Const'r
74: *
75: * @return Horde_ImageGenerator
76: */
77: public function __construct($params)
78: {
79: $this->_params = $params;
80: if (!empty($params['image'])) {
81: $this->_image = $params['image'];
82: }
83: $this->_style = $params['style'];
84: }
85:
86: /**
87: * Create and cache the view.
88: *
89: * @return mixed Views used as gallery key images return Horde_Image,
90: * other views return boolean
91: */
92: public function create()
93: {
94: if (!empty($this->_image)) {
95: // Use Horde_Image since we don't know at this point which
96: // view we have loaded.
97: $img = $this->_image->getHordeImage();
98: $this->_dimensions = $img->getDimensions();
99: }
100:
101: return $this->_create();
102: }
103:
104: /**
105: * Horde_ImageGenerator factory
106: *
107: * @param string $type The type of concrete instance to return.
108: * @param array $params Additional parameters needed for the instance.
109: *
110: * @return Ansel_ImageGenerator
111: * @throws Ansel_Exception
112: */
113: static public function factory($type, $params = array())
114: {
115: $type = basename($type);
116: $class = 'Ansel_ImageGenerator_' . $type;
117: if (class_exists($class)) {
118: $view = new $class($params);
119: // Check that the image object supports what we need for the effect.
120: foreach ($view->need as $need) {
121: if (!Ansel::isAvailable($need)) {
122: $err = sprintf(_("This install does not support the %s feature. Please contact your administrator."), $need);
123: Horde::logMessage($err, 'ERR');
124: throw new Ansel_Exception($err);
125: }
126: }
127: return $view;
128: } else {
129: $err = sprintf(_("Unable to load the definition of %s."), $class);
130: Horde::logMessage($err, 'ERR');
131: throw new Ansel_Exception($err);
132: }
133: }
134:
135: /**
136: * Utility function to make every effort to find a subgallery that
137: * contains images.
138: *
139: * @param Ansel_Gallery $parent The gallery to start looking in
140: *
141: * @return Ansel_Gallery Gallery that has images, or the original $parent
142: */
143: protected function _getGalleryWithImages(Ansel_Gallery $parent)
144: {
145: $galleries = $GLOBALS['injector']
146: ->getInstance('Ansel_Storage')
147: ->listGalleries(array('parent' => $parent->id, 'all_levels' => false));
148:
149: foreach ($galleries as $gallery) {
150: if ($gallery->countImages()) {
151: return $gallery;
152: }
153: $result = $this->_getGalleryWithImages($gallery);
154: if ($result->countImages()) {
155: return $result;
156: }
157: }
158:
159: return $parent;
160: }
161:
162: /**
163: * Utility function to return an array of Horde_Images to use in building a
164: * stack. Returns a random set of 5 images from the gallery, or the
165: * explicitly set key image plus 4 others.
166: *
167: * @return array An array of Horde_Image objects.
168: */
169: protected function _getStackImages()
170: {
171: $images = array();
172: $gallery = $this->_params['gallery'];
173:
174: // Make sure we have images.
175: if (!$gallery->countImages() && $gallery->hasSubGalleries()) {
176: $gallery = $this->_getGalleryWithImages($gallery);
177: }
178:
179: $cnt = min(5, $gallery->countImages());
180: $default = $gallery->get('default');
181: if (!empty($default) && $default > 0) {
182: try {
183: $img = $gallery->getImage($default);
184: $img->load('screen');
185: $images[] = $img->getHordeImage();
186: $cnt--;
187: } catch (Exception $e) {
188: Horde::logMessage($e, 'ERR');
189: }
190: }
191:
192: for ($i = 0; $i < $cnt; $i++) {
193: $rnd = mt_rand(0, $cnt);
194: try {
195: $temp = $gallery->getImages($rnd, 1);
196: if (count($temp)) {
197: $aimg = array_shift($temp);
198: $aimg->load('screen');
199: $images[] = $aimg->getHordeImage();
200: }
201: } catch (Exception $e) {
202: Horde::logMessage($e, 'ERR');
203: }
204: }
205:
206: // Reverse the array to ensure the requested key image
207: // is the last in the array (so it will appear on the top of
208: // the stack.
209: return array_reverse($images);
210: }
211:
212: }
213: