1: <?php
2: /**
3: * The Horde_Mime_Viewer_Base:: class provides the API for specific viewer
4: * drivers to extend.
5: *
6: * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
7: *
8: * See the enclosed file COPYING for license information (LGPL). If you
9: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
10: *
11: * @author Michael Slusarz <slusarz@horde.org>
12: * @category Horde
13: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
14: * @package Mime_Viewer
15: */
16: class Horde_Mime_Viewer_Base
17: {
18: /**
19: * Viewer configuration.
20: *
21: * @var array
22: */
23: protected $_conf = array();
24:
25: /**
26: * The Horde_Mime_Part object to render.
27: *
28: * @var Horde_Mime_Part
29: */
30: protected $_mimepart = null;
31:
32: /**
33: * Required configuration parameters.
34: *
35: * @var array
36: */
37: protected $_required = array();
38:
39: /**
40: * This driver's display capabilities.
41: *
42: * @var array
43: */
44: protected $_capability = array(
45: 'full' => false,
46: 'info' => false,
47: 'inline' => false,
48: 'raw' => false
49: );
50:
51: /**
52: * Metadata for the current viewer/data.
53: *
54: * @var array
55: */
56: protected $_metadata = array(
57: // Is the part *data* compressed (not the rendered data)?
58: 'compressed' => false,
59: // Does this part contain emebedded MIME data?
60: 'embedded' => false,
61: // Force inline display of this part?
62: 'forceinline' => false
63: );
64:
65: /**
66: * Constructor.
67: *
68: * @param Horde_Mime_Part $mime_part The object with the data to be
69: * rendered.
70: * @param array $conf Configuration:
71: * <pre>
72: * temp_file - (callback) A callback function that returns a temporary
73: * filename. Is passed one parameter: a prefix string.
74: * DEFAULT: Uses Horde_Util::getTempFile().
75: * text_filter - (callback) A callback function used to filter text. Is
76: * called the same as Horde_Text_Filter::filter().
77: * DEFAULT: Uses Horde_Text_Filter::filter().
78: * </pre>
79: *
80: * @throws InvalidArgumentException
81: */
82: public function __construct(Horde_Mime_Part $part, array $conf = array())
83: {
84: foreach ($this->_required as $val) {
85: if (!isset($conf[$val])) {
86: throw new InvalidArgumentException(__CLASS__ . ': Missing configuration value (' . $val . ')');
87: }
88: }
89:
90: $this->_mimepart = $part;
91: $this->_conf = $conf;
92: }
93:
94: /**
95: * Sets the Horde_Mime_Part object for the class.
96: *
97: * @param Horde_Mime_Part $mime_part The object with the data to be
98: * rendered.
99: */
100: public function setMimePart(Horde_Mime_Part $mime_part)
101: {
102: $this->_mimepart = $mime_part;
103: }
104:
105: /**
106: * Return the rendered version of the Horde_Mime_Part object.
107: *
108: * @param string $mode The mode:
109: * <pre>
110: * 'full' - A full representation of the MIME part, for use in a view
111: * where the output to the browser can be set to the value
112: * returned in 'type'. This mode should only return a single
113: * MIME ID entry for viewing and should not return any status
114: * information.
115: * 'inline' - A representation of the MIME part that can be viewed inline
116: * on a text/html page that may contain other HTML elements.
117: * 'info' - A representation of the MIME part that can be viewed inline
118: * on an text/html page that may contain other HTML elements.
119: * This view is not a full view, but rather a condensed view of
120: * the contents of the MIME part. This view is intended to be
121: * displayed to the user with the intention that this MIME part's
122: * subparts may also independently be viewed inline.
123: * 'raw' - The raw data of the MIME part, generally useful for downloading
124: * a part. This view exists in case this raw data needs to be
125: * altered in any way.
126: * </pre>
127: *
128: * @return array An array. The keys are the MIME parts that were handled
129: * by the driver. The values are either null (which
130: * indicates the driver is recommending that this
131: * particular MIME ID should not be displayed) or an array
132: * with the following keys:
133: * <pre>
134: * 'data' - (string) The rendered data.
135: * 'status' - (array) An array of status information to be displayed to
136: * the user. Consists of arrays with the following keys:
137: * 'class' - (string) The class to use for display.
138: * 'img' - (string) An image to display.
139: * 'text' - (array) The text to display.
140: * 'type' - (string) The MIME type of the rendered data.
141: * </pre>
142: */
143: public function render($mode)
144: {
145: switch ($mode) {
146: case 'full':
147: try {
148: return $this->_render();
149: } catch (Horde_Exception $e) {
150: $error = $e;
151: }
152: break;
153:
154: case 'inline':
155: try {
156: return $this->_renderInline();
157: } catch (Horde_Exception $e) {
158: $error = $e;
159: }
160:
161: case 'info':
162: try {
163: return $this->_renderInfo();
164: } catch (Horde_Exception $e) {
165: $error = $e;
166: }
167:
168: case 'raw':
169: try {
170: return $this->_renderRaw();
171: } catch (Horde_Exception $e) {
172: $error = $e;
173: }
174: }
175:
176: // TODO: Error handling
177: }
178:
179: /**
180: * Return the full HTML rendered version of the Horde_Mime_Part object.
181: * This MUST be text/html data.
182: *
183: * @return array See render().
184: * @throws Horde_Exception
185: */
186: protected function _render()
187: {
188: $viewer = $this->_getViewer();
189: return $viewer
190: ? $viewer->render('full')
191: : array();
192: }
193:
194: /**
195: * Return the rendered inline version of the Horde_Mime_Part object.
196: * This MUST be text/html data.
197: * This is not a full HTML document - only the HTML necessary to output
198: * the part.
199: *
200: * @return array See render().
201: * @throws Horde_Exception
202: */
203: protected function _renderInline()
204: {
205: $viewer = $this->_getViewer();
206: return $viewer
207: ? $viewer->render('inline')
208: : array();
209: }
210:
211: /**
212: * Return the rendered information about the Horde_Mime_Part object.
213: *
214: * @return array See render().
215: * @throws Horde_Exception
216: */
217: protected function _renderInfo()
218: {
219: $viewer = $this->_getViewer();
220: return $viewer
221: ? $viewer->render('info')
222: : array();
223: }
224:
225: /**
226: * Return the raw representation of the Horde_Mime_Part object.
227: *
228: * @return array See render().
229: * @throws Horde_Exception
230: */
231: protected function _renderRaw()
232: {
233: $viewer = $this->_getViewer();
234: return $viewer
235: ? $viewer->render('raw')
236: : array();
237: }
238:
239: /**
240: * Can this driver render the the data?
241: *
242: * @param string $mode The mode. Either 'full', 'inline', 'info', or
243: * 'raw'.
244: *
245: * @return boolean True if the driver can render the data for the given
246: * view.
247: */
248: public function canRender($mode)
249: {
250: $viewer = $this->_getViewer();
251: if ($viewer) {
252: return $viewer->canRender($mode);
253: }
254:
255: switch ($mode) {
256: case 'full':
257: case 'info':
258: case 'raw':
259: return $this->_capability[$mode];
260:
261: case 'inline':
262: return $this->getConfigParam('inline') &&
263: ($this->_metadata['forceinline'] ||
264: ($this->_capability['inline'] &&
265: ($this->_mimepart->getDisposition() != 'attachment')));
266:
267: default:
268: return false;
269: }
270: }
271:
272: /**
273: * Does this MIME part possibly contain embedded MIME parts?
274: *
275: * @return boolean True if this driver supports parsing embedded MIME
276: * parts.
277: */
278: public function embeddedMimeParts()
279: {
280: $viewer = $this->_getViewer();
281: return $viewer
282: ? $viewer->embeddedMimeParts()
283: : $this->_metadata['embedded'];
284: }
285:
286: /**
287: * If this MIME part can contain embedded MIME part(s), and those part(s)
288: * exist, return a representation of that data.
289: *
290: * @return mixed A Horde_Mime_Part object representing the embedded data.
291: * Returns null if no embedded MIME part(s) exist.
292: */
293: public function getEmbeddedMimeParts()
294: {
295: $viewer = $this->_getViewer();
296: return $viewer
297: ? $viewer->getEmbeddedMimeParts()
298: : $this->_getEmbeddedMimeParts();
299: }
300:
301: /**
302: * If this MIME part can contain embedded MIME part(s), and those part(s)
303: * exist, return a representation of that data.
304: *
305: * @return mixed A Horde_Mime_Part object representing the embedded data.
306: * Returns null if no embedded MIME part(s) exist.
307: */
308: protected function _getEmbeddedMimeParts()
309: {
310: return null;
311: }
312:
313: /**
314: * Return a configuration parameter for the current viewer.
315: *
316: * @param string $param The parameter name.
317: *
318: * @return mixed The value of the parameter; returns null if the
319: * parameter doesn't exist.
320: */
321: public function getConfigParam($param)
322: {
323: return isset($this->_conf[$param])
324: ? $this->_conf[$param]
325: : null;
326: }
327:
328: /**
329: * Sets a configuration parameter for the current viewer.
330: *
331: * @param string $param The parameter name.
332: * @param mixed $value The parameter value.
333: */
334: public function setConfigParam($param, $value)
335: {
336: $this->_conf[$param] = $value;
337: }
338:
339: /**
340: * Returns the driver name for the current object.
341: *
342: * @return string The driver name.
343: */
344: public function getDriver()
345: {
346: return $this->getConfigParam('_driver');
347: }
348:
349: /**
350: * Returns metadata information on the viewer/data.
351: *
352: * @param string $data The metadata key.
353: *
354: * @return mixed The requested information, or null if the key doesn't
355: * exist.
356: */
357: public function getMetadata($data)
358: {
359: return isset($this->_metadata[$data])
360: ? $this->_metadata[$data]
361: : null;
362: }
363:
364: /**
365: * Return the underlying MIME Viewer for this part.
366: *
367: * @return mixed A Horde_Mime_Viewer object, or false if not found.
368: */
369: protected function _getViewer()
370: {
371: return false;
372: }
373:
374: /**
375: * Internal helper function to create render data array for a MIME Part
376: * object that only has a single part.
377: *
378: * @param string $data The rendered data.
379: * @param string $type The rendered type.
380: *
381: * @return array See render().
382: */
383: protected function _renderReturn($data = null, $type = null)
384: {
385: return array(
386: $this->_mimepart->getMimeId() => array(
387: 'data' => (is_null($data) ? $this->_mimepart->getContents() : $data),
388: 'status' => array(),
389: 'type' => (is_null($type) ? $this->_mimepart->getType() : $type)
390: )
391: );
392: }
393:
394: /**
395: * Internal helper function to add base HTML tags to a render() return
396: * array that contains a single MIME part.
397: *
398: * @param array $data See render().
399: *
400: * @return array See render().
401: */
402: protected function _renderFullReturn($data)
403: {
404: if (!empty($data)) {
405: reset($data);
406: $data[key($data)]['data'] = '<html><body>' .
407: $data[key($data)]['data'] .
408: '</body></html>';
409: }
410:
411: return $data;
412: }
413:
414: /**
415: * Returns a temporary file name.
416: *
417: * @return string A temp filename.
418: */
419: protected function _getTempFile()
420: {
421: return ($temp_file = $this->getConfigParam('temp_file'))
422: ? call_user_func($temp_file, __CLASS__)
423: : Horde_Util::getTempFile(__CLASS__);
424: }
425:
426: /**
427: * Filter text.
428: *
429: * @param string $text TODO
430: * @param mixed $driver TODO
431: * @param array $params TODO
432: *
433: * @return string The filtered text.
434: */
435: protected function _textFilter($text, $driver, array $params = array())
436: {
437: return ($text_filter = $this->getConfigParam('text_filter'))
438: ? call_user_func($text_filter, $text, $driver, $params)
439: : Horde_Text_Filter::filter($text, $driver, $params);
440: }
441:
442: }
443: