Overview

Packages

  • Agora
  • None

Classes

  • Agora
  • Agora_Api
  • Agora_Driver
  • Agora_Driver_SplitSql
  • Agora_Driver_Sql
  • Agora_Exception
  • Agora_Factory_Driver
  • Agora_Form_Forum
  • Agora_Form_Message
  • Agora_Form_Search
  • Agora_View
  • Horde_Form_Renderer_MessageForm
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Agora:: class provides basic Agora functionality.
  4:  *
  5:  * Copyright 2003-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 Marko Djukic <marko@oblo.com>
 11:  * @package Agora
 12:  */
 13: class Agora {
 14: 
 15:     /**
 16:      * The virtual path to use for VFS data.
 17:      */
 18:     const VFS_PATH = '.horde/agora/attachments/';
 19:     const AVATAR_PATH = '.horde/agora/avatars/';
 20: 
 21:     /**
 22:      * Determines the requested forum_id, message_id and application by
 23:      * checking first if they are passed as the single encoded var or
 24:      * individual vars.
 25:      *
 26:      * @return array  Forum, message id and application.
 27:      */
 28:     function getAgoraId()
 29:     {
 30:         if (($id = Horde_Util::getFormData('agora')) !== null) {
 31:             if (strstr($id, '.')) {
 32:                 list($forum_id, $message_id) = explode('.', $id, 2);
 33:             } else {
 34:                 $forum_id = $id;
 35:                 $message_id = 0;
 36:             }
 37:         } else {
 38:             $forum_id = Horde_Util::getFormData('forum_id');
 39:             $message_id = Horde_Util::getFormData('message_id');
 40:         }
 41:         $scope = basename(Horde_Util::getFormData('scope', 'agora'));
 42: 
 43:         return array($forum_id, $message_id, $scope);
 44:     }
 45: 
 46:     /**
 47:      * Creates the Agora id.
 48:      *
 49:      * @return string  If passed with the $url parameter, returns a completed
 50:      *                 url with the agora_id tacked on at the end, otherwise
 51:      *                 returns the simple agora_id.
 52:      */
 53:     function setAgoraId($forum_id, $message_id, $url = '', $scope = null, $encode = false)
 54:     {
 55:         $agora_id = $forum_id . '.' . $message_id;
 56: 
 57:         if (!empty($url)) {
 58:             if ($scope) {
 59:                 $url = Horde_Util::addParameter($url, 'scope', $scope, $encode);
 60:             } else {
 61:                 $url = Horde_Util::addParameter($url, 'scope', Horde_Util::getGet('scope', 'agora'), $encode);
 62:             }
 63:             return Horde_Util::addParameter($url, 'agora', $agora_id, $encode);
 64:         }
 65: 
 66:         return $agora_id;
 67:     }
 68: 
 69:     /**
 70:      * Returns a new or the current CAPTCHA string.
 71:      *
 72:      * @param boolean $new  If true, a new CAPTCHA is created and returned.
 73:      *                      The current, to-be-confirmed string otherwise.
 74:      *
 75:      * @return string  A CAPTCHA string.
 76:      */
 77:     function getCAPTCHA($new = false)
 78:     {
 79:         global $session;
 80: 
 81:         if ($new || !$session->get('agora', 'captcha')) {
 82:             $captcha = '';
 83:             for ($i = 0; $i < 5; ++$i) {
 84:                 $captcha .= chr(rand(65, 90));
 85:             }
 86:             $session->set('agora', 'captcha', $captcha);
 87:         }
 88: 
 89:         return $session->get('agora', 'captcha');
 90:     }
 91: 
 92:     /**
 93:      * Formats a list of forums, showing each child of a parent with
 94:      * appropriate indent using '.. ' as a leader.
 95:      *
 96:      * @param array $forums  The list of forums to format.
 97:      *
 98:      * @return array  Formatted forum list.
 99:      */
100:     function formatCategoryTree($forums)
101:     {
102:         /* TODO this doesn't work, as forun_name doesn't contain ":".
103:          * Should use forum_parent_id instead. */
104:         $forums_list = array();
105:         foreach (array_values($forums) as $forum) {
106:             $levels = explode(':', $forum['forum_name']);
107:             $forums_list[$forum['forum_id']] = str_repeat('.. ', count($levels) - 1) . array_pop($levels);
108:         }
109:         return $forums_list;
110:     }
111: 
112:     /**
113:      * Returns the column to sort by, checking first if it is specified in the
114:      * URL, then returning the value stored in prefs.
115:      *
116:      * @param string $view  The view name, used to identify preference settings
117:      *                      for sorting.
118:      *
119:      * @return string  The column to sort by.
120:      */
121:     function getSortBy($view)
122:     {
123:         global $prefs;
124: 
125:         if (($sortby = Horde_Util::getFormData($view . '_sortby')) !== null) {
126:             $prefs->setValue($view . '_sortby', $sortby);
127:         }
128:         $sort_by = $prefs->getValue($view . '_sortby');
129: 
130:         /* BC check for now invalid sort criteria. */
131:         if ($sort_by == 'message_date' || substr($sort_by, 0, 1) == 'l') {
132:             $sort_by = $prefs->getDefault($view . '_sortby');
133:             $prefs->setValue($view . '_sortby', $sortby);
134:         }
135: 
136:         return $sort_by;
137:     }
138: 
139:     /**
140:      * Returns the sort direction, checking first if it is specified in the URL,
141:      * then returning the value stored in prefs.
142:      *
143:      * @param string $view  The view name, used to identify preference settings
144:      *                      for sorting.
145:      *
146:      * @return integer  The sort direction, 0 = ascending, 1 = descending.
147:      */
148:     function getSortDir($view)
149:     {
150:         global $prefs;
151:         if (($sortdir = Horde_Util::getFormData($view . '_sortdir')) !== null) {
152:             $prefs->setValue($view . '_sortdir', $sortdir);
153:         }
154:         return $prefs->getValue($view . '_sortdir');
155:     }
156: 
157:     /**
158:      * Formats column headers have sort links and sort arrows.
159:      *
160:      * @param array  $columns   The columns to format.
161:      * @param string $sort_by   The current 'sort-by' column.
162:      * @param string $sort_dir  The current sort direction.
163:      * @param string $view      The view name, used to identify preference
164:      *                          settings for sorting.
165:      *
166:      * @return array  The formated column headers to be displayed.
167:      */
168:     function formatColumnHeaders($columns, $sort_by, $sort_dir, $view)
169:     {
170:         /* Get the current url, remove any sorting parameters. */
171:         $url = Horde::selfUrl(true);
172:         $url = Horde_Util::removeParameter($url, array($view . '_sortby', $view . '_sortdir'));
173: 
174:         /* Go through the column headers to format and add sorting links. */
175:         $headers = array();
176:         foreach ($columns as $col_name => $col_title) {
177:             $extra = array();
178:             /* Is this a column with two headers? */
179:             if (is_array($col_title)) {
180:                 $keys = array_keys($col_title);
181:                 $extra_name = $keys[0];
182:                 if ($sort_by == $keys[1]) {
183:                     $extra = array($keys[0] => $col_title[$keys[0]]);
184:                     $col_name = $keys[1];
185:                     $col_title = $col_title[$keys[1]];
186:                 } else {
187:                     $extra = array($keys[1] => $col_title[$keys[1]]);
188:                     $col_name = $keys[0];
189:                     $col_title = $col_title[$keys[0]];
190:                 }
191:             }
192:             if ($sort_by == $col_name) {
193:                 /* This column is currently sorted by, plain title and
194:                  * add sort direction arrow. */
195:                 $sort_img = ($sort_dir ? 'za.png' : 'az.png');
196:                 $sort_title = ($sort_dir ? _("Sort Ascending") : _("Sort Descending"));
197:                 $col_arrow = Horde::link(Horde_Util::addParameter($url, array($view . '_sortby' => $col_name, $view . '_sortdir' => $sort_dir ? 0 : 1)), $sort_title) .
198:                     Horde::img($sort_img, $sort_title) . '</a> ';
199:                 $col_class = 'selected';
200:             } else {
201:                 /* Column not currently sorted, add link to sort by
202:                  * this one and no sort arrow. */
203:                 $col_arrow = '';
204:                 $col_title = Horde::link(Horde_Util::addParameter($url, $view . '_sortby', $col_name), sprintf(_("Sort by %s"), $col_title)) . $col_title . '</a>';
205:                 $col_class = 'item';
206:             }
207:             $col_class .= ' leftAlign';
208:             if (count($extra)) {
209:                 list($name, $title) = each($extra);
210:                 $col_title .= '&nbsp;<small>[' .
211:                     Horde::link(Horde_Util::addParameter($url, $view . '_sortby', $name), sprintf(_("Sort by %s"), $title)) . $title . '</a>' .
212:                     ']</small>';
213:                 $col_name = $extra_name;
214:             }
215:             $headers[$col_name] = $col_arrow . $col_title;
216:             $headers[$col_name . '_class_plain'] = $col_class;
217:             $headers[$col_name . '_class'] = empty($col_class) ? '' : ' class="' . $col_class . '"';
218:         }
219: 
220:         return $headers;
221:     }
222: 
223:     /**
224:      * Returns a {@link VFS} instance.
225:      *
226:      * @return VFS  A VFS instance.
227:      */
228:     function getVFS()
229:     {
230:         global $conf;
231: 
232:         if (!isset($conf['vfs']['type'])) {
233:             return PEAR::raiseError(_("The VFS backend needs to be configured to enable attachment uploads."));
234:         }
235: 
236:         try {
237:             return $GLOBALS['injector']->getInstance('Horde_Core_Factory_Vfs')->create();
238:         } catch (Horde_Vfs_Exception $e) {
239:             return PEAR::raiseError($e);
240:         }
241:     }
242: 
243:     function validateAvatar($avatar_path)
244:     {
245:         if (!$GLOBALS['conf']['avatar']['allow_avatars'] || !$avatar_path) {
246:             return false;
247:         }
248: 
249:         preg_match('/^(http|vfs):\/\/(.*)\/(gallery|uploaded|.*)\/(.*\..*)/i',
250:                    $avatar_path, $matches);
251: 
252:         switch ($matches[1]) {
253:         case 'http':
254:             if (!$GLOBALS['conf']['avatar']['enable_external']) {
255:                 /* Avatar is external and external avatars have been
256:                  * disabled. */
257:                 return false;
258:             }
259:             $dimensions = @getimagesize($avatar_path);
260:             if (($dimensions === false) ||
261:                 ($dimensions[0] > $GLOBALS['conf']['avatar']['max_width']) ||
262:                 ($dimensions[1] > $GLOBALS['conf']['avatar']['max_height'])) {
263:                 /* Avatar is external and external avatars are
264:                  * enabled, but the image is too wide or high. */
265:                 return false;
266:             } else {
267:                 $avatar = null;
268: 
269:                 $flock = fopen($avatar_path, 'r');
270:                 while (!feof($flock)) {
271:                     $avatar .= fread($flock, 2048);
272:                 }
273:                 fclose($flock);
274: 
275:                 if (strlen($avatar) > ($GLOBALS['conf']['avatar']['max_size'] * 1024)) {
276:                     /* Avatar is external and external avatars have
277:                      * been enabled, but the file is too large. */
278:                     return false;
279:                 }
280:             }
281:             return true;
282: 
283:         case 'vfs':
284:             switch ($matches[3]) {
285:             case 'gallery':
286:                 /* Avatar is within the gallery. */
287:                 return $GLOBALS['conf']['avatar']['enable_gallery'];
288: 
289:             case 'uploaded':
290:                 /* Avatar is within the uploaded avatar collection. */
291:                 return $GLOBALS['conf']['avatar']['enable_uploads'];
292: 
293:             default:
294:                 /* Malformed URL. */
295:                 return false;
296:             }
297:             break;
298: 
299:         default:
300:             /* Malformed URL. */
301:             return false;
302:         }
303: 
304:         return false;
305:     }
306: 
307:     function getAvatarUrl($avatar_path, $scopeend_sid = true)
308:     {
309:         if (!$avatar_path) {
310:             return PEAR::raiseError(_("Malformed avatar."));
311:         }
312: 
313:         preg_match('/^(http|vfs):\/\/(.*)\/(gallery|uploaded|.*)\/(.*\..*)/i',
314:                    $avatar_path, $matches);
315: 
316:         switch ($matches[1]) {
317:         case 'http':
318:             /* HTTP URL's are already "real" */
319:             break;
320: 
321:         case 'vfs':
322:             /* We need to do some re-writing to VFS paths. */
323:             switch ($matches[3]) {
324:             case 'gallery':
325:                 $avatar_collection_id = '1';
326:                 break;
327: 
328:             case 'uploaded':
329:                 $avatar_collection_id = '2';
330:                 break;
331: 
332:             default:
333:                 return PEAR::raiseError(_("Malformed database entry."));
334:             }
335: 
336:             $avatar_path = Horde::url('avatars/?id=' . urlencode($matches[4]) . ':' . $avatar_collection_id, true, $scopeend_sid);
337:             break;
338:         }
339: 
340:         return $avatar_path;
341:     }
342: 
343:     /**
344:      * Send new posts to a distribution email address for a wider audience
345:      *
346:      * @param int $message_id  Identifier of message to be distributed
347:      *
348:      * @throws Horde_Mime_Exception
349:      */
350:     function distribute($message_id)
351:     {
352:         global $conf;
353: 
354:         $storage = $GLOBALS['injector']->getInstance('Agora_Factory_Driver')->create();
355:         $message = $storage->getMessage($message_id);
356:         $forum = $storage->getForum($message['forum_id']);
357: 
358:         if (empty($forum['forum_distribution_address'])) {
359:             return;
360:         }
361: 
362:         $mail = new Horde_Mime_Mail();
363:         $mail->addHeader('X-Horde-Agora-Post', $message_id);
364:         $mail->addHeader('From', strpos($message['message_author'], '@') ? $message['message_author'] : $forum['forum_distribution_address']);
365:         $mail->addHeader('Subject', '[' . $forum['forum_name'] . '] ' . $message['message_subject']);
366:         $mail->addHeader('To', $forum['forum_distribution_address']);
367:         $mail->setBody($message['body']);
368: 
369:         $mail->send($GLOBALS['injector']->getInstance('Horde_Mail'));
370:     }
371: }
372: 
API documentation generated by ApiGen