· 10 years ago · Sep 14, 2016, 02:04 PM
1<?php
2/**
3* @package EasyDiscuss
4* @copyright Copyright (C) 2010 - 2015 Stack Ideas Sdn Bhd. All rights reserved.
5* @license GNU/GPL, see LICENSE.php
6* EasyDiscuss is free software. This version may have been modified pursuant
7* to the GNU General Public License, and as distributed it includes or
8* is derivative of works licensed under the GNU General Public License or
9* other free or open source software licenses.
10* See COPYRIGHT.php for copyright notices and details.
11*/
12defined('_JEXEC') or die('Unauthorized Access');
13
14jimport('joomla.filesystem.file');
15jimport('joomla.filesystem.folder');
16jimport('joomla.html.parameter');
17jimport('joomla.access.access');
18jimport('joomla.application.component.model');
19
20// Include legacy object
21require_once(__DIR__ . '/legacy.php');
22
23// Include constants
24require_once(__DIR__ . '/dependencies.php');
25
26class ED
27{
28 /**
29 * Initializes the css, js and necessary dependencies for EasyDiscuss
30 *
31 * @since 4.0
32 * @access public
33 * @param string
34 * @return
35 */
36 public static function init($location = 'site')
37 {
38 static $loaded = array();
39
40 if (!isset($loaded[$location])) {
41
42 $input = JFactory::getApplication()->input;
43
44 // Determines if we should force compilationg (Only allow for super admin)
45 $recompile = false;
46
47 if (ED::isSiteAdmin()) {
48 $recompile = $input->get('compile', false, 'bool');
49 }
50
51 // If location is provided, we should respect the location
52 $customLocation = $input->get('location', $location, 'word');
53 $locations = array($location);
54
55 if ($recompile && $customLocation == 'all') {
56 $locations = array('site', 'admin');
57 }
58
59 foreach ($locations as $location) {
60 // Render the JS compiler
61 $compiler = ED::compiler($location);
62
63 if ($recompile) {
64 $compiler->compile(true, true);
65 }
66 }
67
68 // Attach those scripts onto the head of the page now.
69 $compiler->attach();
70
71 // Attach the stylesheets
72 $stylesheet = ED::stylesheet($location);
73 $stylesheet->attach();
74
75 $loaded[$location] = true;
76 }
77
78 return $loaded[$location];
79 }
80
81 /**
82 * Formats and returns the appropriate cdn url
83 *
84 * @since 4.0
85 * @access public
86 * @param string
87 * @return
88 */
89 public static function getCdnUrl()
90 {
91 static $cdnUrl = false;
92
93 if (!$cdnUrl) {
94 $config = ED::config();
95 $cdnUrl = $config->get('system_cdn_url');
96
97 if (!$cdnUrl) {
98 return $cdnUrl;
99 }
100
101 if (stristr($cdnUrl, 'http://') === false && stristr($cdnUrl, 'https://') === false) {
102 $cdnUrl = 'http://' . $cdnUrl;
103 }
104 }
105
106 return $cdnUrl;
107 }
108
109 /**
110 * Singleton version for the ajax library
111 *
112 * @since 4.0
113 * @access public
114 * @param string
115 * @return
116 */
117 public static function ajax()
118 {
119 static $ajax = null;
120
121 if (!$ajax) {
122
123 require_once(__DIR__ . '/ajax/ajax.php');
124
125 $ajax = new EasyDiscussAjax();
126 }
127
128 return $ajax;
129 }
130
131 public static function _()
132 {
133 return ED::getHelper( func_get_args() );
134 }
135
136 /**
137 * Retrieves the token
138 *
139 * @since 4.0
140 * @access public
141 * @param string
142 * @return
143 */
144 public static function getToken($contents = '')
145 {
146 $token = JFactory::getSession()->getFormToken();
147
148 return $token;
149 }
150
151 public static function getHash( $seed = '' )
152 {
153 if( DiscussHelper::getJoomlaVersion() >= '2.5' )
154 {
155 return JApplication::getHash( $seed );
156 }
157
158 return JUtility::getHash( $seed );
159 }
160
161 /**
162 * Retrieves a jdate object with the correct speficied timezone offset
163 *
164 * @since 4.0
165 * @access public
166 * @param string
167 * @return
168 */
169 public static function dateWithOffSet($str='')
170 {
171 $userTZ = self::getTimeZoneOffset();
172 $date = ED::date($str);
173
174 $user = JFactory::getUser();
175 $config = ED::Config();
176 $jConfig = ED::JConfig();
177
178 // temporary ignore the dst in joomla 1.6
179
180 if ($user->id != 0) {
181 $userTZ = $user->getParam('timezone');
182 }
183
184 if (empty($userTZ)) {
185 $userTZ = $jConfig->get('offset');
186 }
187
188 $tmp = new DateTimeZone($userTZ);
189 $date->setTimeZone($tmp);
190
191 return $date;
192 }
193
194 public static function getBBCodeParser() {
195 require_once( DISCUSS_CLASSES . '/decoda.php');
196 $decoda = new DiscussDecoda( '', array('strictMode'=>false) );
197 return $decoda;
198 }
199
200 public static function getHelper()
201 {
202 static $helpers = array();
203
204 $args = func_get_args();
205
206 if (func_num_args() == 0 || empty($args) || empty($args[0]))
207 {
208 return false;
209 }
210
211 $sig = md5(serialize($args));
212
213 if( !array_key_exists($sig, $helpers) )
214 {
215 $helper = preg_replace('/[^A-Z0-9_\.-]/i', '', $args[0]);
216 $file = DISCUSS_HELPERS . '/' . JString::strtolower($helper) . '.php';
217
218 if( JFile::exists($file) )
219 {
220 require_once($file);
221 $class = 'Discuss' . ucfirst( $helper ) . 'Helper';
222
223 switch (func_num_args()) {
224 case '2':
225 $helpers[$sig] = new $class($args[1]);
226 break;
227 case '3':
228 $helpers[$sig] = new $class($args[1], $args[2]);
229 break;
230 case '4':
231 $helpers[$sig] = new $class($args[1], $args[2], $args[3]);
232 break;
233 case '5':
234 $helpers[$sig] = new $class($args[1], $args[2], $args[3], $args[4]);
235 break;
236 case '6':
237 $helpers[$sig] = new $class($args[1], $args[2], $args[3], $args[4], $args[5]);
238 break;
239 case '7':
240 $helpers[$sig] = new $class($args[1], $args[2], $args[3], $args[4], $args[5], $args[6]);
241 break;
242 case '1':
243 default:
244 $helpers[$sig] = new $class();
245 break;
246 }
247 }
248 else
249 {
250 $helpers[$sig] = false;
251 }
252 }
253
254 return $helpers[$sig];
255 }
256
257 /**
258 * Retrieve specific helper objects.
259 *
260 * @param string $helper The helper class . Class name should be the same name as the file. e.g EasyDiscussXXXHelper
261 * @return object Helper object.
262 **/
263 public static function getHelperLegacy( $helper )
264 {
265 static $obj = array();
266
267 if( !isset( $obj[ $helper ] ) )
268 {
269 $file = DISCUSS_HELPERS . '/' . JString::strtolower( $helper ) . '.php';
270
271 if( JFile::exists( $file ) )
272 {
273 require_once( $file );
274 $class = 'Discuss' . ucfirst( $helper ) . 'Helper';
275
276 $obj[ $helper ] = new $class();
277 }
278 else
279 {
280 $obj[ $helper ] = false;
281 }
282 }
283
284 return $obj[ $helper ];
285 }
286
287 public static function getRegistry( $data = '' )
288 {
289 if( ED::getJoomlaVersion() >= '1.6' )
290 {
291 $registry = new JRegistry($data);
292 }
293 else
294 {
295 require_once DISCUSS_CLASSES . '/registry.php';
296 $registry = new DiscussRegistry($data);
297 }
298
299 return $registry;
300 }
301
302 public static function getXML($data, $isFile = true)
303 {
304 if( ED::getJoomlaVersion() >= '1.6' )
305 {
306 $xml = JFactory::getXML($data, true);
307 }
308 else
309 {
310 // Disable libxml errors and allow to fetch error information as needed
311 libxml_use_internal_errors(true);
312
313 if ($isFile)
314 {
315 // Try to load the XML file
316 //$xml = simplexml_load_file($data, 'JXMLElement');
317 $xml = simplexml_load_file($data);
318 }
319 else
320 {
321 // Try to load the XML string
322 //$xml = simplexml_load_string($data, 'JXMLElement');
323 $xml = simplexml_load_string($data);
324 }
325
326 if (empty($xml))
327 {
328 // There was an error
329 JError::raiseWarning(100, JText::_('JLIB_UTIL_ERROR_XML_LOAD'));
330
331 if ($isFile)
332 {
333 JError::raiseWarning(100, $data);
334 }
335
336 foreach (libxml_get_errors() as $error)
337 {
338 JError::raiseWarning(100, 'XML: ' . $error->message);
339 }
340 }
341 }
342
343 return $xml;
344 }
345
346 public static function getUnansweredCount( $categoryId = '0', $excludeFeatured = false )
347 {
348 $db = DiscussHelper::getDBO();
349
350 $excludeCats = DiscussHelper::getPrivateCategories();
351 $catModel = ED::model('Categories');
352
353 if( !is_array( $categoryId ) && !empty( $categoryId ))
354 {
355 $categoryId = array( $categoryId );
356 }
357
358 $childs = array();
359 if( $categoryId )
360 {
361 foreach( $categoryId as $id )
362 {
363 $data = $catModel->getChildIds( $id );
364
365 if( $data )
366 {
367 foreach( $data as $childCategory )
368 {
369 $childs[] = $childCategory;
370 }
371 }
372 $childs[] = $id;
373 }
374 }
375
376 if( !$categoryId )
377 {
378 $categoryIds = false;
379 }
380 else
381 {
382 $categoryIds = array_diff($childs, $excludeCats);
383 }
384
385 $query = 'SELECT COUNT(a.`id`) FROM `#__discuss_posts` AS a';
386 $query .= ' LEFT JOIN `#__discuss_posts` AS b';
387 $query .= ' ON a.`id`=b.`parent_id`';
388 $query .= ' AND b.`published`=' . $db->Quote('1');
389 $query .= ' WHERE a.`parent_id` = ' . $db->Quote('0');
390 $query .= ' AND a.`published`=' . $db->Quote('1');
391 $query .= ' AND a.`answered` = 0';
392 $query .= ' AND a.`isresolve`=' . $db->Quote('0');
393 $query .= ' AND b.`id` IS NULL';
394
395
396 if( $categoryIds )
397 {
398 if( count( $categoryIds ) == 1 )
399 {
400 $categoryIds = array_shift( $categoryIds );
401 $query .= ' AND a.`category_id` = ' . $db->Quote( $categoryIds );
402 }
403 else
404 {
405 $query .= ' AND a.`category_id` IN (' . implode( ',', $categoryIds ) .')';
406 }
407 }
408
409 if( $excludeFeatured )
410 {
411 $query .= ' AND a.`featured`=' . $db->Quote( '0' );
412 }
413
414 if (!ED::isSiteAdmin() && !ED::isModerator()) {
415 $query .= ' AND a.`private`=' . $db->Quote(0);
416 }
417
418
419 $db->setQuery( $query );
420
421 return $db->loadResult();
422 }
423
424 public static function getFeaturedCount( $categoryId )
425 {
426 $db = DiscussHelper::getDBO();
427
428 $query = 'SELECT COUNT(1) as `CNT` FROM `#__discuss_posts` AS a';
429
430 $query .= ' WHERE a.`featured` = ' . $db->Quote('1');
431 $query .= ' AND a.`parent_id` = ' . $db->Quote('0');
432 $query .= ' AND a.`published` = ' . $db->Quote('1');
433 $query .= ' AND a.`category_id`= ' . $db->Quote( $categoryId );
434
435 $db->setQuery($query);
436
437 $result = $db->loadResult();
438
439 return $result;
440 }
441
442 /**
443 * Allows caller to queue a message
444 *
445 * @since 4.0
446 * @access public
447 * @param string
448 * @return
449 */
450 public static function setMessage($message, $type = 'info')
451 {
452 $session = JFactory::getSession();
453
454 $msgObj = new stdClass();
455 $msgObj->message = JText::_($message);
456 $msgObj->type = strtolower($type);
457
458 //save messsage into session
459 $session->set('discuss.message.queue', $msgObj, 'DISCUSS.MESSAGE');
460 }
461
462 public static function getMessageQueue()
463 {
464 $session = JFactory::getSession();
465 $msgObj = $session->get('discuss.message.queue', null, 'DISCUSS.MESSAGE');
466
467 //clear messsage into session
468 $session->set('discuss.message.queue', null, 'DISCUSS.MESSAGE');
469
470 return $msgObj;
471 }
472
473 public static function getAlias( $title, $type='post', $id='0' )
474 {
475
476 $items = explode( ' ', $title );
477 foreach( $items as $index => $item )
478 {
479 if( strpos( $item, '*' ) !== false )
480 {
481 $items[$index] = 'censored';
482 }
483 }
484
485 $title = implode( $items, ' ' );
486
487 $alias = DiscussHelper::permalinkSlug($title);
488
489 // Make sure no such alias exists.
490 $i = 1;
491 while( DiscussRouter::_isAliasExists( $alias, $type, $id ) )
492 {
493 $alias = DiscussHelper::permalinkSlug( $title ) . '-' . $i;
494 $i++;
495 }
496
497 return $alias;
498 }
499
500 public static function permalinkSlug( $string, $uid = null )
501 {
502 $config = DiscussHelper::getConfig();
503 if ($config->get( 'main_sef_unicode' )) {
504
505 if ($uid && is_numeric($uid)) {
506 $string = $uid . ':' . $string;
507 }
508
509 // Unicode support.
510 $alias = DiscussHelper::permalinkUnicodeSlug($string);
511
512 } else {
513 // Replace accents to get accurate string
514 //$alias = DiscussRouter::replaceAccents( $string );
515 // hällö wörldß became hallo-world instead haelloe-woerld thus above line is commented
516 // for consistency with joomla
517
518 $alias = JFilterOutput::stringURLSafe( $string );
519
520 // check if anything return or not. If not, then we give a date as the alias.
521 if(trim(str_replace('-', '', $alias)) == '') {
522 $alias = ED::date()->format("Y-m-d-H-i-s");
523 }
524 }
525 return $alias;
526 }
527
528 public static function permalinkUnicodeSlug( $string )
529 {
530 $slug = '';
531 if(DiscussHelper::getJoomlaVersion() >= '1.6')
532 {
533 $slug = JFilterOutput::stringURLUnicodeSlug($string);
534 }
535 else
536 {
537 //replace double byte whitespaces by single byte (Far-East languages)
538 $slug = preg_replace('/\xE3\x80\x80/', ' ', $string);
539
540 // remove any '-' from the string as they will be used as concatenator.
541 // Would be great to let the spaces in but only Firefox is friendly with this
542 $slug = str_replace('-', ' ', $slug);
543
544 // replace forbidden characters by whitespaces
545 $slug = preg_replace( '#[:\#\*"@+=;!><&\.%()\]\/\'\\\\|\[]#', "\x20", $slug );
546
547 //delete all '?'
548 $slug = str_replace('?', '', $slug);
549
550 //trim white spaces at beginning and end of alias, make lowercase
551 $slug = trim(JString::strtolower($slug));
552
553 // remove any duplicate whitespace and replace whitespaces by hyphens
554 $slug =preg_replace('#\x20+#','-', $slug);
555 }
556
557 return $slug;
558 }
559
560 public static function getNotification()
561 {
562 static $notify = false;
563
564 if( !$notify )
565 {
566
567 $notify = ED::notifications();
568 }
569 return $notify;
570
571 }
572
573 public static function getMailQueue()
574 {
575 static $mailq = false;
576
577 if (!$mailq) {
578 $mailq = ED::mailqueue();
579 }
580
581 return $mailq;
582 }
583
584 public static function getSiteSubscriptionClass()
585 {
586 static $sitesubscriptionclass = false;
587
588 if( !$sitesubscriptionclass )
589 {
590 require_once DISCUSS_CLASSES . '/subscription.php';
591
592 $sitesubscriptionclass = new DiscussSubscription();
593 }
594 return $sitesubscriptionclass;
595 }
596
597 public static function getLoginHTML( $returnURL )
598 {
599 $tpl = new DiscussThemes();
600 $tpl->set( 'return' , base64_encode( $returnURL ) );
601
602 return $tpl->fetch( 'ajax.login.php' );
603 }
604
605 public static function getLocalParser()
606 {
607 $data = new stdClass();
608
609 $contents = JFile::read( DISCUSS_ADMIN_ROOT . '/easydiscuss.xml' );
610
611 $parser = new DiscussXMLHelper( $contents );
612
613 return $parser;
614 }
615
616 /**
617 * Retrieves the current version of EasyDiscuss
618 *
619 * @since 4.0
620 * @access public
621 * @param string
622 * @return
623 */
624 public static function getLocalVersion()
625 {
626 static $version = null;
627
628 if (is_null($version)) {
629
630 $manifest = DISCUSS_ADMIN_ROOT . '/easydiscuss.xml';
631
632 $parser = JFactory::getXML($manifest, true);
633
634 $version = (string) $parser->version;
635 }
636
637 return $version;
638 }
639
640 /**
641 * Retrieves the server's version of EasyDiscuss
642 *
643 * @since 4.0
644 * @access public
645 * @param string
646 * @return
647 */
648 public static function getVersion()
649 {
650 static $version = null;
651
652 if (is_null($version)) {
653
654 $connector = ED::connector();
655 $connector->addUrl(ED_UPDATER);
656 $connector->connect();
657
658 $contents = $connector->getResult(ED_UPDATER);
659
660 if (!$contents) {
661 $version = false;
662
663 return $version;
664 }
665
666 $obj = json_decode($contents);
667
668 if (!$obj) {
669 $version = false;
670
671 return $version;
672 }
673
674 $version = $obj->version;
675 }
676
677 return $version;
678 }
679
680 /**
681 * Retrieves the default value from the configuration file
682 *
683 * @since 4.0
684 * @access public
685 * @param string
686 * @return
687 */
688 public static function getDefaultConfigValue($key, $defaultVal = null)
689 {
690 static $defaults = null;
691
692 if (is_null($defaults)) {
693
694 $file = DISCUSS_ADMIN_ROOT . '/defaults/configuration.ini';
695 $contents = JFile::read($file);
696
697 $defaults = new JRegistry($contents);
698 }
699
700 return $defaults->get($key, $defaultVal);
701 }
702
703 /**
704 * Retrieves the core configuration object for EasyDiscuss.
705 *
706 * @since 1.0
707 * @access public
708 * @param null
709 * @return JRegistry
710 */
711 public static function config()
712 {
713 if (defined('ED_CLI')) {
714 return false;
715 }
716
717 static $config = null;
718
719 if (is_null($config)) {
720
721 // Render the data from the ini first.
722 $raw = JFile::read(DISCUSS_ADMIN_ROOT . '/defaults/configuration.ini');
723
724 $config = ED::getRegistry($raw);
725
726 // Retrieve the data from the db
727 $db = ED::db();
728 $query = 'SELECT ' . $db->qn('params') . ' FROM ' . $db->qn('#__discuss_configs');
729 $query .= 'WHERE ' . $db->qn('name') . '=' . $db->Quote('config');
730
731 $db->setQuery($query);
732 $result = $db->loadResult();
733
734 $config->loadString($result, 'INI');
735 }
736
737 return $config;
738 }
739
740 public static function getPostAccess( DiscussPost $post , DiscussCategory $category )
741 {
742 static $access = null;
743
744 if( is_null( $access[ $post->id ] ) )
745 {
746 // Load default ini data first
747 $access[ $post->id ] = new DiscussPostAccess( $post , $category);
748 }
749
750 return $access[ $post->id ];
751 }
752
753 /*
754 * Method used to determine whether the user a guest or logged in user.
755 * return : boolean
756 */
757 public static function isLoggedIn()
758 {
759 $my = JFactory::getUser();
760 $loggedIn = (empty($my) || $my->id == 0) ? false : true;
761 return $loggedIn;
762 }
763
764 public static function isSiteAdmin($userId = null)
765 {
766 static $loaded = array();
767
768 $sig = is_null($userId) ? 'me' : $userId ;
769
770 if(! isset( $loaded[$sig] ) )
771 {
772 $my = JFactory::getUser( $userId );
773
774 $admin = false;
775 if(DiscussHelper::getJoomlaVersion() >= '1.6')
776 {
777 $admin = $my->authorise('core.admin');
778 }
779 else
780 {
781 $admin = $my->usertype == 'Super Administrator' || $my->usertype == 'Administrator' ? true : false;
782 }
783
784 $loaded[ $sig ] = $admin;
785 }
786
787 return $loaded[ $sig ];
788 }
789
790 public static function isMine($uid)
791 {
792 $my = JFactory::getUser();
793
794 if($my->id == 0)
795 return false;
796
797 if( empty($uid) )
798 return false;
799
800 $mine = $my->id == $uid ? 1 : 0;
801 return $mine;
802 }
803
804 public static function getUserId( $username )
805 {
806 static $userids = array();
807
808 if( !isset( $userids[ $username ] ) || empty($userids[$username]) )
809 {
810 $db = DiscussHelper::getDBO();
811
812 // first get from user alias
813 $query = 'SELECT `id` FROm `#__discuss_users` WHERE `alias` = ' . $db->quote( $username );
814 $db->setQuery( $query );
815 $userid = $db->loadResult();
816
817 // then get from user nickname
818 if (!$userid) {
819 $query = 'SELECT `id` FROm `#__discuss_users` WHERE `nickname` = ' . $db->quote( $username );
820 $db->setQuery( $query );
821 $userid = $db->loadResult();
822 }
823
824 // then get from username
825 if (!$userid) {
826 $query = 'SELECT `id` FROM `#__users` WHERE `username`=' . $db->quote( $username );
827 $db->setQuery( $query );
828
829 $userid = $db->loadResult();
830 }
831
832 if (!$userid) {
833 $query = 'SELECT `id` FROM `#__users` WHERE `name`=' . $db->quote( $username );
834 $db->setQuery( $query );
835
836 $userid = $db->loadResult();
837 }
838
839
840
841 $userids[$username] = $userid;
842 }
843
844 return $userids[$username];
845 }
846
847 public static function getAjaxURL()
848 {
849 $uri = JFactory::getURI();
850 $language = $uri->getVar('lang', 'none');
851 $app = JFactory::getApplication();
852 $config = DiscussHelper::getJConfig();
853 $router = $app->getRouter();
854 $url = rtrim( JURI::base() , '/' );
855
856 $url = $url . '/index.php?option=com_easydiscuss&lang=' . $language;
857
858 if( $router->getMode() == JROUTER_MODE_SEF && JPluginHelper::isEnabled("system","languagefilter") )
859 {
860 $rewrite = $config->get('sef_rewrite');
861
862 $base = str_ireplace( JURI::root( true ) , '' , $uri->getPath() );
863 $path = $rewrite ? $base : JString::substr( $base , 10 );
864 $path = JString::trim( $path , '/' );
865 $parts = explode( '/' , $path );
866
867 $language = addslashes($language);
868
869 if($parts) {
870 // First segment will always be the language filter.
871 $language = reset( $parts );
872 } else {
873 $language = 'none';
874 }
875
876 if ($rewrite) {
877 $url = rtrim( JURI::root() , '/' ) . '/' . $language . '/?option=com_easydiscuss';
878 $language = 'none';
879 } else {
880 $url = rtrim( JURI::root() , '/' ) . '/index.php/' . $language . '/?option=com_easydiscuss';
881 }
882 }
883
884 return $url;
885 }
886
887 public static function getBaseUrl()
888 {
889 static $url;
890
891 if (isset($url)) return $url;
892
893 if( DiscussHelper::getJoomlaVersion() >= '1.6' )
894 {
895 $uri = JFactory::getURI();
896 $language = $uri->getVar( 'lang' , 'none' );
897 $app = JFactory::getApplication();
898 $config = DiscussHelper::getJConfig();
899 $router = $app->getRouter();
900 $url = rtrim( JURI::base() , '/' );
901
902 $url = $url . '/index.php?option=com_easydiscuss&lang=' . $language;
903
904 if( $router->getMode() == JROUTER_MODE_SEF && JPluginHelper::isEnabled("system","languagefilter") )
905 {
906 $rewrite = $config->get('sef_rewrite');
907
908 $base = str_ireplace( JURI::root( true ) , '' , $uri->getPath() );
909 $path = $rewrite ? $base : JString::substr( $base , 10 );
910 $path = JString::trim( $path , '/' );
911 $parts = explode( '/' , $path );
912
913 if( $parts )
914 {
915 // First segment will always be the language filter.
916 $language = reset( $parts );
917 }
918 else
919 {
920 $language = 'none';
921 }
922
923 if( $rewrite )
924 {
925 $url = rtrim( JURI::root() , '/' ) . '/' . $language . '/?option=com_easydiscuss';
926 $language = 'none';
927 }
928 else
929 {
930 $url = rtrim( JURI::root() , '/' ) . '/index.php/' . $language . '/?option=com_easydiscuss';
931 }
932 }
933 }
934 else
935 {
936
937 $url = rtrim( JURI::root() , '/' ) . '/index.php?option=com_easydiscuss';
938 }
939
940 $menu = JFactory::getApplication()->getmenu();
941
942 if( !empty($menu) )
943 {
944 $item = $menu->getActive();
945 if( isset( $item->id) )
946 {
947 $url .= '&Itemid=' . $item->id;
948 }
949 }
950
951 // Some SEF components tries to do a 301 redirect from non-www prefix to www prefix.
952 // Need to sort them out here.
953 $currentURL = isset( $_SERVER[ 'HTTP_HOST' ] ) ? $_SERVER[ 'HTTP_HOST' ] : '';
954
955 if( !empty( $currentURL ) )
956 {
957 // When the url contains www and the current accessed url does not contain www, fix it.
958 if( stristr($currentURL , 'www' ) === false && stristr( $url , 'www') !== false )
959 {
960 $url = str_ireplace( 'www.' , '' , $url );
961 }
962
963 // When the url does not contain www and the current accessed url contains www.
964 if( stristr( $currentURL , 'www' ) !== false && stristr( $url , 'www') === false )
965 {
966 $url = str_ireplace( '://' , '://www.' , $url );
967 }
968 }
969
970 return $url;
971 }
972
973 /**
974 * Loads the default languages for EasyDiscuss
975 *
976 * @since 4.0
977 * @access public
978 * @param string
979 * @return
980 */
981 public static function loadLanguages($path = JPATH_ROOT)
982 {
983 static $loaded = array();
984
985 if (!isset($loaded[$path])) {
986 $lang = JFactory::getLanguage();
987
988 // Load site's default language file.
989 $lang->load('com_easydiscuss', $path);
990
991 $loaded[$path] = true;
992 }
993
994 return $loaded[$path];
995 }
996
997 public static function getDurationString($dateTimeDiffObj)
998 {
999 $lang = JFactory::getLanguage();
1000 $lang->load('com_easydiscuss', JPATH_ROOT);
1001
1002 $data = $dateTimeDiffObj;
1003 $returnStr = '';
1004
1005 if ($data->daydiff <= 0) {
1006 $timeDate = explode(':', $data->timediff);
1007
1008 // ensure all has a colon
1009 if (!isset($timeDate[1])) {
1010 $timeDate[1] = null;
1011 }
1012
1013 if (intval($timeDate[0], 10) >= 1) {
1014 $returnStr = ED::string()->getNoun('COM_EASYDISCUSS_HOURS_AGO', intval($timeDate[0], 10), true);
1015
1016 } else if(intval($timeDate[1], 10) >= 2) {
1017 $returnStr = ED::string()->getNoun('COM_EASYDISCUSS_MINUTES_AGO', intval($timeDate[1], 10), true);
1018
1019 } else {
1020 $returnStr = JText::_('COM_EASYDISCUSS_LESS_THAN_A_MINUTE_AGO');
1021 }
1022
1023 } else if (($data->daydiff >= 1) && ($data->daydiff < 7)) {
1024 $returnStr = ED::string()->getNoun('COM_EASYDISCUSS_DAYS_AGO', $data->daydiff, true);
1025
1026 } else if ($data->daydiff >= 7 && $data->daydiff <= 30) {
1027 $returnStr = (intval($data->daydiff/7, 10) == 1 ? JText::_('COM_EASYDISCUSS_ONE_WEEK_AGO') : JText::sprintf('COM_EASYDISCUSS_WEEKS_AGO', intval($data->daydiff/7, 10)));
1028
1029 } else {
1030 $returnStr = JText::_('COM_EASYDISCUSS_MORE_THAN_A_MONTH_AGO');
1031 }
1032
1033 return $returnStr;
1034 }
1035
1036 public static function storeSession($data, $key, $ns = 'com_easydiscuss')
1037 {
1038 $mySess = JFactory::getSession();
1039 $mySess->set($key, $data, $ns);
1040 }
1041
1042 public static function getSession($key, $ns = 'com_easydiscuss')
1043 {
1044 $data = null;
1045
1046 $mySess = JFactory::getSession();
1047 if($mySess->has($key, $ns))
1048 {
1049 $data = $mySess->get($key, '', $ns);
1050 $mySess->clear($key, $ns);
1051 return $data;
1052 }
1053 else
1054 {
1055 return $data;
1056 }
1057 }
1058
1059 public static function isNew( $noofdays )
1060 {
1061 $config = DiscussHelper::getConfig();
1062 $isNew = ($noofdays <= $config->get('layout_daystostaynew', 7)) ? true : false;
1063
1064 return $isNew;
1065 }
1066
1067 public static function getExternalLink($link)
1068 {
1069 $uri = JURI::getInstance();
1070 $domain = $uri->toString(array('scheme', 'host', 'port'));
1071
1072 return $domain . '/' . ltrim(EDR::_($link, false), '/');
1073 }
1074
1075 public static function uploadAvatar($profile, $isFromBackend = false)
1076 {
1077 jimport('joomla.utilities.error');
1078 jimport('joomla.filesystem.file');
1079 jimport('joomla.filesystem.folder');
1080
1081 $my = JFactory::getUser();
1082 $mainframe = JFactory::getApplication();
1083 $config = ED::config();
1084
1085 $avatar_config_path = $config->get('main_avatarpath');
1086 $avatar_config_path = rtrim($avatar_config_path, '/');
1087 $avatar_config_path = JString::str_ireplace('/', DIRECTORY_SEPARATOR, $avatar_config_path);
1088
1089 // Get the upload path
1090 $upload_path = JPATH_ROOT . '/' . $avatar_config_path;
1091 $rel_upload_path = $avatar_config_path;
1092
1093 $error = null;
1094 $file = JRequest::getVar('Filedata', '', 'files', 'array');
1095
1096 // Check whether the upload folder exist or not. if not create it.
1097 if (!JFolder::exists($upload_path)) {
1098 if (!JFolder::create($upload_path)) {
1099 // Redirect
1100 if (!$isFromBackend) {
1101 ED::setMessageQueue(JText::_( 'COM_EASYDISCUSS_FAILED_TO_CREATE_UPLOAD_FOLDER' ), 'error');
1102 $mainframe->redirect( EDR::_('index.php?option=com_easydiscuss&view=profile', false));
1103 return;
1104 }
1105
1106 // From backend
1107 $mainframe->redirect( EDR::_('index.php?option=com_easydiscuss&view=users', false), JText::_('COM_EASYDISCUSS_FAILED_TO_CREATE_UPLOAD_FOLDER'), 'error');
1108 return;
1109 }
1110 }
1111
1112 // Makesafe on the file
1113 $date = ED::date();
1114 $file_ext = ED::Image()->getFileExtention($file['name']);
1115 $file['name'] = $my->id . '_' . JFile::makeSafe(md5($file['name'].$date->toSql())) . '.' . strtolower($file_ext);
1116
1117
1118 if (isset($file['name'])) {
1119 $target_file_path = $upload_path;
1120 $relative_target_file = $rel_upload_path . '/' . $file['name'];
1121 $target_file = JPath::clean($target_file_path . '/' . JFile::makeSafe($file['name']));
1122 $original = JPath::clean($target_file_path . '/' . 'original_' . JFile::makeSafe($file['name']));
1123
1124 $isNew = false;
1125
1126 if (!ED::Image()->canUpload($file, $error)) {
1127 if (!$isFromBackend) {
1128 ED::setMessageQueue(JText::_($error), 'error');
1129 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=profile&layout=edit', false));
1130 return;
1131 }
1132
1133 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=users', false), JText::_($error), 'error');
1134
1135 return;
1136 }
1137
1138 if ((int)$file['error'] != 0) {
1139 if (!$isFromBackend) {
1140 ED::setMessageQueue( $file['error'] , 'error');
1141 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=profile&layout=edit', false));
1142 return;
1143 }
1144 //from backend
1145 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=users', false), $file['error'], 'error');
1146
1147 return;
1148 }
1149
1150 //rename the file 1st.
1151 $oldAvatar = $profile->avatar;
1152 $tempAvatar = '';
1153 $isNew = ($oldAvatar == 'default.png')? true : false ;
1154
1155 if (!$isNew) {
1156 $session = JFactory::getSession();
1157 $sessionId = $session->getToken();
1158
1159 $fileExt = JFile::getExt(JPath::clean($target_file_path . '/' . $oldAvatar));
1160 $tempAvatar = JPath::clean($target_file_path . '/' . $sessionId . '.' . $fileExt);
1161
1162 // Test if old original file exists. If exist, remove it.
1163 if (JFile::exists($target_file_path . '/original_' . $oldAvatar)) {
1164 JFile::delete($target_file_path . '/original_' . $oldAvatar);
1165 }
1166
1167 JFile::move($target_file_path . '/' . $oldAvatar, $tempAvatar);
1168 }
1169
1170 if (JFile::exists($target_file) || JFolder::exists($target_file)) {
1171 if (!$isNew) {
1172 //rename back to the previous one.
1173 JFile::move($tempAvatar, $target_file_path . '/' . $oldAvatar);
1174 }
1175
1176 if (!$isFromBackend) {
1177 DiscussHelper::setMessageQueue( JText::sprintf('COM_EASYDISCUSS_FILE_ALREADY_EXISTS', $relative_target_file) , 'error');
1178 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=profile', false));
1179 return;
1180 }
1181
1182 //from backend
1183 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=users', false), JText::sprintf('COM_EASYDISCUSS_FILE_ALREADY_EXISTS', $relative_target_file), 'error');
1184 return;
1185 }
1186
1187 // image size should be in ratio of 1:1
1188 $configImageWidth = $config->get('layout_avatarwidth', 160);
1189 $configImageHeight = $configImageWidth;
1190 $originalImageWidth = $config->get('layout_originalavatarwidth', 400);
1191 $originalImageHeight = $originalImageWidth;
1192
1193 // Copy the original image files over
1194 $image = ED::simpleimage();
1195 $image->load($file['tmp_name']);
1196
1197 //$image->resizeToFill( $originalImageWidth , $originalImageHeight );
1198
1199 // By Kevin Lankhorst
1200 $image->resizeOriginal($originalImageWidth, $originalImageHeight, $configImageWidth, $configImageHeight);
1201
1202 $image->save($original, $image->image_type);
1203 unset($image);
1204
1205 $image = ED::simpleimage();
1206 $image->load($file['tmp_name']);
1207 $image->resizeToFill($configImageWidth, $configImageHeight);
1208 $image->save($target_file, $image->image_type);
1209
1210 //now we update the user avatar. If needed, we remove the old avatar.
1211 if (!$isNew) {
1212 if (JFile::exists($tempAvatar)) {
1213 JFile::delete($tempAvatar);
1214 }
1215 }
1216
1217 return JFile::makeSafe($file['name']);
1218 } else {
1219 return 'default.png';
1220 }
1221
1222 }
1223
1224 public static function uploadCategoryAvatar( $category, $isFromBackend = false )
1225 {
1226 return ED::uploadMediaAvatar( 'category', $category, $isFromBackend);
1227 }
1228
1229 public static function uploadMediaAvatar($mediaType, $mediaTable, $isFromBackend = false)
1230 {
1231 jimport('joomla.utilities.error');
1232 jimport('joomla.filesystem.file');
1233 jimport('joomla.filesystem.folder');
1234
1235 $my = JFactory::getUser();
1236 $mainframe = JFactory::getApplication();
1237 $config = ED::getConfig();
1238
1239 // required params
1240 $layout_type = ($mediaType == 'category') ? 'categories' : 'teamblogs';
1241 $view_type = ($mediaType == 'category') ? 'categories' : 'teamblogs';
1242 $default_avatar_type = ($mediaType == 'category') ? 'default_category.png' : 'default_team.png';
1243
1244 if (!$isFromBackend && $mediaType == 'category') {
1245 $url = 'index.php?option=com_easydiscuss&view=categories';
1246 ED::setMessage(JText::_('COM_EASYDISCUSS_NO_PERMISSION_TO_UPLOAD_AVATAR') , 'warning');
1247 $mainframe->redirect(EDR::_($url, false));
1248 }
1249
1250 $avatar_config_path = ($mediaType == 'category') ? $config->get('main_categoryavatarpath') : $config->get('main_teamavatarpath');
1251 $avatar_config_path = rtrim($avatar_config_path, '/');
1252 $avatar_config_path = str_replace('/', DIRECTORY_SEPARATOR, $avatar_config_path);
1253
1254 $upload_path = JPATH_ROOT . '/' . $avatar_config_path;
1255 $rel_upload_path = $avatar_config_path;
1256
1257 $err = null;
1258 $file = JRequest::getVar('Filedata', '', 'files', 'array');
1259
1260 //check whether the upload folder exist or not. if not create it.
1261 if (!JFolder::exists($upload_path)) {
1262 if (!JFolder::create($upload_path)) {
1263 // Redirect
1264 if(!$isFromBackend) {
1265 ED::setMessage(JText::_('COM_EASYDISCUSS_IMAGE_UPLOADER_FAILED_TO_CREATE_UPLOAD_FOLDER') , 'error');
1266 $this->setRedirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false));
1267 } else {
1268 //from backend
1269 $this->setRedirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false), JText::_('COM_EASYDISCUSS_IMAGE_UPLOADER_FAILED_TO_CREATE_UPLOAD_FOLDER'), 'error');
1270 }
1271 return;
1272 } else {
1273 // folder created. now copy index.html into this folder.
1274 if (!JFile::exists( $upload_path . '/index.html')) {
1275 $targetFile = DISCUSS_ROOT . '/index.html';
1276 $destFile = $upload_path . '/index.html';
1277
1278 if(JFile::exists($targetFile))
1279 JFile::copy($targetFile, $destFile);
1280 }
1281 }
1282 }
1283
1284 //makesafe on the file
1285 $file['name'] = $mediaTable->id . '_' . JFile::makeSafe($file['name']);
1286
1287 if (isset($file['name'])) {
1288 $target_file_path = $upload_path;
1289 $relative_target_file = $rel_upload_path . '/' . $file['name'];
1290 $target_file = JPath::clean($target_file_path . '/' . JFile::makeSafe($file['name']));
1291 $isNew = false;
1292
1293 require_once(__DIR__ . '/image/image.php');
1294 require_once(__DIR__ . '/simpleimage/simpleimage.php');
1295
1296 if (!EasyDiscussImage::canUpload($file, $err)) {
1297 if(!$isFromBackend) {
1298 ED::setMessage( JText::_($err), 'error');
1299 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false));
1300 } else {
1301 // From backend
1302 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories'), JText::_($err), 'error');
1303 }
1304 return;
1305 }
1306
1307 if (0 != (int)$file['error']) {
1308 if (!$isFromBackend) {
1309 ED::setMessage($file['error'], 'error');
1310 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false));
1311 } else {
1312 // From backend
1313 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false), $file['error'], 'error');
1314 }
1315 return;
1316 }
1317
1318 // Rename the file 1st.
1319 $oldAvatar = (empty($mediaTable->avatar)) ? $default_avatar_type : $mediaTable->avatar;
1320 $tempAvatar = '';
1321 if ($oldAvatar != $default_avatar_type) {
1322 $session = JFactory::getSession();
1323 $sessionId = $session->getToken();
1324
1325 $fileExt = JFile::getExt(JPath::clean($target_file_path . '/' . $oldAvatar));
1326 $tempAvatar = JPath::clean($target_file_path . '/' . $sessionId . '.' . $fileExt);
1327
1328 JFile::move($target_file_path . '/' . $oldAvatar, $tempAvatar);
1329 } else {
1330 $isNew = true;
1331 }
1332
1333
1334 if (JFile::exists($target_file)) {
1335 if ($oldAvatar != $default_avatar_type) {
1336 //rename back to the previous one.
1337 JFile::move($tempAvatar, $target_file_path . '/' . $oldAvatar);
1338 }
1339
1340 if (!$isFromBackend) {
1341 ED::setMessage(JText::sprintf('ERROR.FILE_ALREADY_EXISTS', $relative_target_file), 'error');
1342 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false));
1343 } else {
1344 //from backend
1345 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false), JText::sprintf('ERROR.FILE_ALREADY_EXISTS', $relative_target_file), 'error');
1346 }
1347 return;
1348 }
1349
1350 if (JFolder::exists($target_file)) {
1351
1352 if ($oldAvatar != $default_avatar_type) {
1353 //rename back to the previous one.
1354 JFile::move($tempAvatar, $target_file_path . '/' . $oldAvatar);
1355 }
1356
1357 if (!$isFromBackend) {
1358 //JError::raiseNotice(100, JText::sprintf('ERROR.FOLDER_ALREADY_EXISTS',$relative_target_file));
1359 ED::setMessage(JText::sprintf('ERROR.FOLDER_ALREADY_EXISTS', $relative_target_file), 'error');
1360 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false));
1361 } else {
1362 //from backend
1363 $mainframe->redirect(EDR::_('index.php?option=com_easydiscuss&view=categories', false), JText::sprintf('ERROR.FILE_ALREADY_EXISTS', $relative_target_file), 'error');
1364 }
1365 return;
1366 }
1367
1368 $configImageWidth = DISCUSS_AVATAR_LARGE_WIDTH;
1369 $configImageHeight = DISCUSS_AVATAR_LARGE_HEIGHT;
1370
1371 $image = new EasyDiscussSimpleImage();
1372 $image->load($file['tmp_name']);
1373 $image->resize($configImageWidth, $configImageHeight);
1374 $image->save($target_file, $image->image_type);
1375
1376 //now we update the user avatar. If needed, we remove the old avatar.
1377 if ($oldAvatar != $default_avatar_type) {
1378 if (JFile::exists($tempAvatar)) {
1379 JFile::delete($tempAvatar);
1380 }
1381 }
1382
1383 return JFile::makeSafe($file['name']);
1384 } else {
1385 return $default_avatar_type;
1386 }
1387
1388 }
1389
1390 /**
1391 * Applies word filtering
1392 *
1393 * @since 4.0
1394 * @access public
1395 * @param string
1396 * @return
1397 */
1398 public static function wordFilter($text)
1399 {
1400 $config = ED::Config();
1401
1402 if (empty($text)) {
1403 return $text;
1404 }
1405
1406 if (trim($text) == '') {
1407 return $text;
1408 }
1409
1410 if ($config->get('main_filterbadword', 1) && $config->get('main_filtertext', '') != '') {
1411
1412 require_once DISCUSS_HELPERS . '/filter.php';
1413 // filter out bad words.
1414 $bwFilter = new BadWFilter();
1415 $textToBeFilter = explode(',', $config->get('main_filtertext'));
1416
1417 // lets do some AI here. for each string, if there is a space,
1418 // remove the space and make it as a new filter text.
1419 if( count($textToBeFilter) > 0 )
1420 {
1421 $newFilterSet = array();
1422 foreach( $textToBeFilter as $item)
1423 {
1424 if( JString::stristr($item, ' ') !== false )
1425 {
1426 $newKeyWord = JString::str_ireplace(' ', '', $item);
1427 $newFilterSet[] = $newKeyWord;
1428 }
1429 } // foreach
1430
1431 if( count($newFilterSet) > 0 )
1432 {
1433 $tmpNewFitler = array_merge($textToBeFilter, $newFilterSet);
1434 $textToBeFilter = array_unique($tmpNewFitler);
1435 }
1436
1437 }//end if
1438
1439 $bwFilter->strings = $textToBeFilter;
1440
1441 //to be filtered text
1442 $bwFilter->text = $text;
1443 $new_text = $bwFilter->filter();
1444
1445 $text = $new_text;
1446 }
1447
1448 return $text;
1449 }
1450
1451 /**
1452 * Formats a discussion object
1453 *
1454 * @since 4.0
1455 * @access public
1456 * @param string
1457 * @return
1458 */
1459 public static function formatPost($rows, $isSearch = false , $isFrontpage = false)
1460 {
1461 // If there is no items, skip this altogether
1462 if (!$rows) {
1463 return $rows;
1464 }
1465
1466 $posts = array();
1467
1468 foreach ($rows as $row) {
1469
1470 // Load it into our post library
1471 $post = ED::post($row);
1472
1473 if ($isFrontpage) {
1474 $model = ED::model('Posts');
1475 $post->lastReply = $model->getLastReply($post->id);
1476 }
1477
1478 $posts[] = $post;
1479 }
1480
1481 return $posts;
1482 }
1483
1484 public static function formatComments($comments)
1485 {
1486 if (!$comments) {
1487 return false;
1488 }
1489
1490 $path = JPATH_ADMINISTRATOR . '/components/com_easydiscuss/includes/events/events.php';
1491
1492 include_once($path);
1493
1494 $config = ED::config();
1495
1496 $result = array();
1497
1498 foreach ($comments as $row) {
1499
1500 $comment = ED::table('Comment');
1501 $comment->bind($row);
1502
1503 $comment->duration = ED::date()->toLapsed($comment->modified);
1504
1505 $creator = ED::user($comment->user_id);
1506 $comment->creator = $creator;
1507
1508 if ($config->get('main_content_trigger_comments')) {
1509
1510 // process content plugins
1511 $comment->content = $comment->comment;
1512
1513 EasyDiscussEvents::importPlugin('content');
1514 EasyDiscussEvents::onContentPrepare('comment', $comment);
1515
1516 $comment->event = new stdClass();
1517
1518 $results = EasyDiscussEvents::onContentBeforeDisplay('comment', $comment);
1519 $comment->event->beforeDisplayContent = trim(implode("\n", $results));
1520
1521 $results = EasyDiscussEvents::onContentAfterDisplay('comment', $comment);
1522 $comment->event->afterDisplayContent = trim(implode("\n", $results));
1523
1524 $comment->comment = $comment->content;
1525 unset($comment->content);
1526
1527 $comment->comment = ED::badwords()->filter($comment->comment);
1528 }
1529
1530 $result[] = $comment;
1531 }
1532
1533 return $result;
1534 }
1535
1536 /**
1537 * Formats the necessary output for reply items
1538 *
1539 * @since 4.0
1540 * @access public
1541 * @param string
1542 * @return
1543 */
1544 public static function formatReplies($result, $category = null, $pagination = true, $acceptedReply = false)
1545 {
1546 $config = ED::config();
1547
1548 if (!$result) {
1549 return $result;
1550 }
1551
1552 $limitstart = JFactory::getApplication()->input->get('limitstart', 0);
1553 $replies = array();
1554
1555 foreach ($result as $key => $row) {
1556 $reply = ED::post($row);
1557
1558 $reply->permalink = EDR::getReplyRoute($reply->parent_id, $reply->id);
1559
1560 // Default reply permalink title; specifically for accepted answer.
1561 $reply->seq = JText::_('COM_EASYDISCUSS_REPLY_PERMALINK_TITLE');
1562
1563 if (!$acceptedReply) {
1564 $reply->seq = $key + 1;
1565
1566 if ($pagination) {
1567 $reply->seq = $limitstart ? $key + $limitstart + 1 : $key + 1;
1568 }
1569 }
1570
1571 if ($config->get('main_comment')) {
1572 $commentLimit = $config->get('main_comment_pagination') ? $config->get('main_comment_pagination_count') : null;
1573 $reply->comments = $reply->getComments($commentLimit);
1574
1575 // get post comments count
1576 $reply->commentsCount = $reply->getTotalComments();
1577 }
1578
1579 $replies[] = $reply;
1580 }
1581
1582 return $replies;
1583 }
1584
1585 public static function formatUsers( $result )
1586 {
1587 if( !$result )
1588 {
1589 return $result;
1590 }
1591
1592 $total = count( $result );
1593
1594 $authorIds = array();
1595 for( $i =0 ; $i < $total; $i++ )
1596 {
1597 $item = $result[ $i ];
1598 $authorIds[] = $item->id;
1599 }
1600
1601 // Reduce SQL queries by pre-loading all author object.
1602 $authorIds = array_unique($authorIds);
1603 ED::user($authorIds);
1604
1605 $users = array();
1606 for( $i =0 ; $i < $total; $i++ )
1607 {
1608 $row =& $result[ $i ];
1609
1610 $user = ED::user($row->id);
1611 $users[] = $user;
1612 }
1613
1614 return $users;
1615 }
1616
1617 public static function getVoters($id, $limit='5')
1618 {
1619 $config = DiscussHelper::getConfig();
1620
1621 $table = DiscussHelper::getTable( 'Post' );
1622 $voters = $table->getVoters($id, $limit);
1623
1624 $data = new stdClass();
1625 $data->voters = '';
1626 $data->shownVoterCount = '';
1627
1628 if(!empty($voters))
1629 {
1630 $data->shownVoterCount = count($voters);
1631
1632 foreach($voters as $voter)
1633 {
1634 $displayname = $config->get('layout_nameformat');
1635
1636 switch($displayname)
1637 {
1638 case "name" :
1639 $votername = $voter->name;
1640 break;
1641 case "username" :
1642 $votername = $voter->username;
1643 break;
1644 case "nickname" :
1645 default :
1646 $votername = (empty($voter->nickname)) ? $voter->name : $voter->nickname;
1647 break;
1648 }
1649
1650 if(!empty($data->voters))
1651 {
1652 $data->voters .= ', ';
1653 }
1654
1655 $data->voters .= '<a href="' . DiscussRouter::_( 'index.php?option=com_easydiscuss&view=profile&id=' . $voter->user_id ) . '">' . $votername . '</a>';
1656 }
1657 }
1658
1659 return $data;
1660 }
1661
1662 public static function getJoomlaVersion()
1663 {
1664 $jVerArr = explode('.', JVERSION);
1665 $jVersion = $jVerArr[0] . '.' . $jVerArr[1];
1666
1667 return $jVersion;
1668 }
1669
1670 public static function isJoomla31()
1671 {
1672 return DiscussHelper::getJoomlaVersion() >= '3.1';
1673 }
1674
1675 public static function isJoomla30()
1676 {
1677 return DiscussHelper::getJoomlaVersion() >= '3.0';
1678 }
1679
1680 public static function isJoomla25()
1681 {
1682 return DiscussHelper::getJoomlaVersion() >= '1.6' && DiscussHelper::getJoomlaVersion() <= '2.5';
1683 }
1684
1685 public static function isJoomla15()
1686 {
1687 return DiscussHelper::getJoomlaVersion() == '1.5';
1688 }
1689
1690 public static function getDefaultSAIds()
1691 {
1692 $saUserId = '62';
1693
1694 if(DiscussHelper::getJoomlaVersion() >= '1.6')
1695 {
1696 $saUsers = DiscussHelper::getSAUsersIds();
1697 $saUserId = $saUsers[0];
1698 }
1699
1700 return $saUserId;
1701 }
1702
1703 /**
1704 * Used in J1.5!. To retrieve list of superadmin users's id.
1705 * array
1706 */
1707 public static function getSAUsersIds15()
1708 {
1709 $db = DiscussHelper::getDBO();
1710
1711 $query = 'SELECT `id` FROM `#__users`';
1712 $query .= ' WHERE (LOWER( usertype ) = ' . $db->Quote('super administrator');
1713 $query .= ' OR `gid` = ' . $db->Quote('25') . ')';
1714 $query .= ' ORDER BY `id` ASC';
1715
1716 $db->setQuery($query);
1717 $result = $db->loadResultArray();
1718
1719 $result = (empty($result)) ? array( '62' ) : $result;
1720
1721 return $result;
1722 }
1723
1724 /**
1725 * Used in J1.6!. To retrieve list of superadmin users's id.
1726 * array
1727 */
1728 public static function getSAUsersIds()
1729 {
1730 if( ED::getJoomlaVersion() < '1.6' ) {
1731 return ED::getSAUsersIds15();
1732 }
1733
1734 $db = DiscussHelper::getDBO();
1735
1736 $query = 'SELECT a.`id`, a.`title`';
1737 $query .= ' FROM `#__usergroups` AS a';
1738 $query .= ' LEFT JOIN `#__usergroups` AS b ON a.lft > b.lft AND a.rgt < b.rgt';
1739 $query .= ' GROUP BY a.id';
1740 $query .= ' ORDER BY a.lft ASC';
1741
1742 $db->setQuery($query);
1743 $result = $db->loadObjectList();
1744
1745 $saGroup = array();
1746 foreach($result as $group)
1747 {
1748 if(JAccess::checkGroup($group->id, 'core.admin'))
1749 {
1750 $saGroup[] = $group;
1751 }
1752 }
1753
1754 //now we got all the SA groups. Time to get the users
1755 $saUsers = array();
1756 if(count($saGroup) > 0)
1757 {
1758 foreach($saGroup as $sag)
1759 {
1760 $userArr = JAccess::getUsersByGroup($sag->id);
1761 if(count($userArr) > 0)
1762 {
1763 foreach($userArr as $user)
1764 {
1765 $saUsers[] = $user;
1766 }
1767 }
1768 }
1769 }
1770
1771 return $saUsers;
1772 }
1773
1774 /**
1775 * Generates a html code for category selection.
1776 *
1777 * @access public
1778 * @param int $parentId if this option spcified, it will list the parent and all its childs categories.
1779 * @param int $userId if this option specified, it only return categories created by this userId
1780 * @param string $outType The output type. Currently supported links and drop down selection
1781 * @param string $eleName The element name of this populated categeries provided the outType os dropdown selection.
1782 * @param string $default The default selected value. If given, it used at dropdown selection (auto select)
1783 * @param boolean $isWrite Determine whether the categories list used in write new page or not.
1784 * @param boolean $isPublishedOnly If this option is true, only published categories will fetched.
1785 * @param array $exclusion A list of excluded categories that it should not be including
1786 */
1787
1788 public static function populateCategories($parentId, $userId, $outType, $eleName, $default = false, $isWrite = false, $isPublishedOnly = false, $showPrivateCat = true , $disableContainers = false , $customClass = 'form-control', $exclusion = array(), $aclType = DISCUSS_CATEGORY_ACL_ACTION_VIEW, $sorting = false)
1789 {
1790 $model = ED::model('Categories');
1791 $parentCat = null;
1792
1793 if (!empty($userId)) {
1794 $parentCat = $model->getParentCategories($userId, 'poster', $isPublishedOnly, $showPrivateCat, $exclusion, $aclType, $sorting);
1795
1796 } else if (!empty($parentId)) {
1797 $parentCat = $model->getParentCategories($parentId, 'category', $isPublishedOnly, $showPrivateCat, $exclusion, $aclType, $sorting);
1798
1799 } else {
1800 $parentCat = $model->getParentCategories('', 'all', $isPublishedOnly, $showPrivateCat, $exclusion, $aclType, $sorting);
1801 }
1802
1803 // If the result == null
1804 if (empty($parentCat)) {
1805 return;
1806 }
1807
1808 $ignorePrivate = false;
1809
1810 switch($outType) {
1811 case 'link' :
1812 $ignorePrivate = false;
1813 break;
1814 case 'select':
1815 default:
1816 $ignorePrivate = true;
1817 break;
1818 }
1819
1820 $selectACLOnly = false;
1821
1822 if ($isWrite) {
1823 $ignorePrivate = false;
1824 $selectACLOnly = true;
1825 }
1826
1827 if (!empty($parentCat)) {
1828
1829 for ($i = 0; $i < count($parentCat); $i++) {
1830
1831 $parent =& $parentCat[$i];
1832
1833 //reset
1834 $parent->childs = null;
1835
1836 ED::buildNestedCategories($parent->id, $parent, $ignorePrivate, $isPublishedOnly, $showPrivateCat, $selectACLOnly, $exclusion);
1837 }//for $i
1838 }//end if !empty $parentCat
1839
1840 $formEle = '';
1841
1842 foreach ($parentCat as $category) {
1843
1844 $selected = ($category->id == $default) ? ' selected="selected"' : '';
1845
1846 if ($default === false) {
1847 $selected = $category->default ? ' selected="selected"' : '';
1848 }
1849
1850 $style = '';
1851 $disabled = '';
1852
1853 // @rule: Test if the category should just act as a container
1854 if ($disableContainers) {
1855 $disabled = $category->container ? ' disabled="disabled"' : '';
1856 $style = $disabled ? ' style="font-weight:700;"' : '';
1857 }
1858
1859 $formEle .= '<option value="' . $category->id . '" ' . ' data-ed-move-post-category-id=' . $category->id . ' ' . $selected . $disabled . $style . '>' . JText::_( $category->title ) . '</option>';
1860
1861 ED::accessNestedCategories($category, $formEle, '0', $default, $outType , '' , $disableContainers);
1862 }
1863
1864 $selected = empty($default) ? ' selected="selected"' : '';
1865
1866 $html = '';
1867 $html .= '<select name="' . $eleName . '" id="' . $eleName .'" class="' . $customClass . '">';
1868
1869 if (!$isWrite)
1870 $html .= '<option value="0">' . JText::_('COM_EASYDISCUSS_SELECT_PARENT_CATEGORY') . '</option>';
1871 else
1872 $html .= '<option value="0" ' . $selected . '>' . JText::_('COM_EASYDISCUSS_SELECT_CATEGORY') . '</option>';
1873 $html .= $formEle;
1874 $html .= '</select>';
1875
1876 return $html;
1877 }
1878
1879 public static function buildNestedCategories($parentId, $parent, $ignorePrivate = false, $isPublishedOnly = false, $showPrivate = true, $selectACLOnly = false, $exclusion = array())
1880 {
1881 $catsModel = ED::model('Categories');
1882
1883 // [model:category]
1884 $catModel = ED::model('Category');
1885
1886 $childs = $catsModel->getChildCategories($parentId, $isPublishedOnly, $showPrivate, $exclusion);
1887
1888 $aclType = ( $selectACLOnly ) ? DISCUSS_CATEGORY_ACL_ACTION_SELECT : DISCUSS_CATEGORY_ACL_ACTION_VIEW;
1889
1890 $accessibleCatsIds = ED::getAccessibleCategories($parentId, $aclType);
1891
1892 if (!empty($childs)) {
1893
1894 for($j = 0; $j < count($childs); $j++) {
1895 $child = $childs[$j];
1896 $child->count = $catModel->getTotalPostCount($child->id);
1897 $child->childs = null;
1898
1899 if (!$ignorePrivate) {
1900
1901 if (count($accessibleCatsIds) > 0) {
1902
1903 $access = false;
1904
1905 foreach ($accessibleCatsIds as $canAccess) {
1906
1907 if ($canAccess->id == $child->id) {
1908 $access = true;
1909 }
1910 }
1911
1912 if (!$access)
1913 continue;
1914 } else {
1915 continue;
1916 }
1917 }
1918
1919 if (!ED::buildNestedCategories($child->id, $child, $ignorePrivate, $isPublishedOnly, $showPrivate, $selectACLOnly, $exclusion)) {
1920 $parent->childs[] = $child;
1921 }
1922 }// for $j
1923
1924 if (!empty($parent->childs)) {
1925 $parent->childs = array_reverse($parent->childs);
1926 }
1927 } else {
1928 return false;
1929 }
1930 }
1931
1932 public static function accessNestedCategories($arr, &$html, $deep='0', $default='0', $type='select', $linkDelimiter = '' , $disableContainers = false )
1933 {
1934 $config = DiscussHelper::getConfig();
1935 if(isset($arr->childs) && is_array($arr->childs))
1936 {
1937 $sup = '<sup>|_</sup>';
1938 $space = '';
1939 $ld = (empty($linkDelimiter)) ? '>' : $linkDelimiter;
1940
1941 if($type == 'select' || $type == 'list')
1942 {
1943 $deep++;
1944 for($d=0; $d < $deep; $d++)
1945 {
1946 $space .= ' ';
1947 }
1948 }
1949
1950 if($type == 'list' && !empty($arr->childs))
1951 {
1952 $html .= '<ul>';
1953 }
1954
1955 for($j = 0; $j < count($arr->childs); $j++)
1956 {
1957 $child = $arr->childs[$j];
1958
1959 switch($type)
1960 {
1961 case 'select':
1962 $selected = ($child->id == $default) ? ' selected="selected"' : '';
1963
1964 if( !$default )
1965 {
1966 $selected = $child->default ? ' selected="selected"' : '';
1967 }
1968
1969 $disabled = '';
1970 $style = '';
1971
1972 // @rule: Test if the category should just act as a container
1973 if( $disableContainers )
1974 {
1975 $disabled = $child->container ? ' disabled="disabled"' : '';
1976 $style = $disabled ? ' style="font-weight:700;"' : '';
1977 }
1978
1979 $html .= '<option value="'.$child->id.'" ' . $selected . $disabled . $style . '>' . $space . $sup . $child->title . '</option>';
1980 break;
1981 case 'list':
1982 $expand = !empty($child->childs)? '<span onclick="EasyDiscuss.$(this).parents(\'li:first\').toggleClass(\'expand\');">[+] </span>' : '';
1983 $html .= '<li><div>' . $space . $sup . $expand . '<a href="' . DiscussRouter::getCategoryRoute( $child->id ) . '">' . $child->title . '</a> <b>(' . $child->count . ')</b></div>';
1984 break;
1985 case 'listlink':
1986 $str = '<li><a href="' . DiscussRouter::getCategoryRoute( $child->id ) . '">';
1987 $str .= (empty($html)) ? $child->title : $ld . ' ' . $child->title;
1988 $str .= '</a></li>';
1989 $html .= $str;
1990 break;
1991 default:
1992 $str = '<a href="' . DiscussRouter::getCategoryRoute( $child->id ) . '">';
1993 //str .= (empty($html)) ? $child->title : $ld . ' ' . $child->title;
1994 $str .= (empty($html)) ? $child->title : $ld . ' ' . $child->title;
1995 $str .= '</a></li>';
1996 $html .= $str;
1997 }
1998
1999 if( !$config->get('layout_category_one_level', 0) )
2000 {
2001 DiscussHelper::accessNestedCategories($child, $html, $deep, $default, $type, $linkDelimiter , $disableContainers );
2002 }
2003
2004
2005 if($type == 'list')
2006 {
2007 $html .= '</li>';
2008 }
2009 }
2010
2011 if($type == 'list' && !empty($arr->childs))
2012 {
2013 $html .= '</ul>';
2014 }
2015 }
2016 else
2017 {
2018 return false;
2019 }
2020 }
2021
2022 public static function accessNestedCategoriesId($arr, &$newArr)
2023 {
2024 if(isset($arr->childs) && is_array($arr->childs))
2025 {
2026 //$modelSubscribe = ED::model( 'Subscribe' );
2027 //$subscribers = $modelSubscribe->getSiteSubscribers('instant');
2028
2029 for($j = 0; $j < count($arr->childs); $j++)
2030 {
2031 $child = $arr->childs[$j];
2032
2033 $newArr[] = $child->id;
2034 DiscussHelper::accessNestedCategoriesId($child, $newArr);
2035 }
2036 }
2037 else
2038 {
2039 return false;
2040 }
2041 }
2042
2043 /**
2044 * function to retrieve the linkage backward from a child id.
2045 * return the full linkage from child up to parent
2046 */
2047
2048 public static function populateCategoryLinkage($childId)
2049 {
2050 $arr = array();
2051 $category = DiscussHelper::getTable( 'Category' );
2052 $category->load($childId);
2053
2054 $obj = new stdClass();
2055 $obj->id = $category->id;
2056 $obj->title = $category->title;
2057 $obj->alias = $category->alias;
2058
2059 $arr[] = $obj;
2060
2061 if((!empty($category->parent_id)))
2062 {
2063 DiscussHelper::accessCategoryLinkage($category->parent_id, $arr);
2064 }
2065
2066 $arr = array_reverse($arr);
2067 return $arr;
2068
2069 }
2070
2071 public static function accessCategoryLinkage($childId, &$arr)
2072 {
2073 $category = DiscussHelper::getTable( 'Category' );
2074
2075 $category->load($childId);
2076
2077 $obj = new stdClass();
2078 $obj->id = $category->id;
2079 $obj->title = $category->title;
2080 $obj->alias = $category->alias;
2081
2082 $arr[] = $obj;
2083
2084 if((!empty($category->parent_id)))
2085 {
2086 DiscussHelper::accessCategoryLinkage($category->parent_id, $arr);
2087 }
2088 else
2089 {
2090 return false;
2091 }
2092 }
2093
2094 /**
2095 * $post - post jtable object
2096 * $parent - post's parent id.
2097 * $isNew - indicate this is a new post or not.
2098 */
2099
2100 public static function sendNotification( $post, $parent = 0, $isNew, $postOwner, $prevPostStatus)
2101 {
2102 JFactory::getLanguage()->load( 'com_easydiscuss' , JPATH_ROOT );
2103
2104 $config = DiscussHelper::getConfig();
2105 $notify = DiscussHelper::getNotification();
2106
2107 $emailPostTitle = $post->title;
2108 $modelSubscribe = ED::model( 'Subscribe' );
2109
2110 //get all admin emails
2111 $adminEmails = array();
2112 $ownerEmails = array();
2113 $newPostOwnerEmails = array();
2114 $postSubscriberEmails = array();
2115 $participantEmails = array();
2116
2117 $catSubscriberEmails = array();
2118
2119 if( empty( $parent ) )
2120 {
2121 // only new post we notify admin.
2122 if($config->get( 'notify_admin' ))
2123 {
2124 $admins = $notify->getAdminEmails();
2125
2126 if(! empty($admins))
2127 {
2128 foreach($admins as $admin)
2129 {
2130 $adminEmails[] = $admin->email;
2131 }
2132 }
2133 }
2134
2135 // notify post owner too when moderate is on
2136 if( !empty( $postOwner ) )
2137 {
2138 $postUser = JFactory::getUser( $postOwner );
2139 $newPostOwnerEmails[] = $postUser->email;
2140 }
2141 else
2142 {
2143 $newPostOwnerEmails[] = $post->poster_email;
2144 }
2145
2146 }
2147 else
2148 {
2149 // if this is a new reply, notify post owner.
2150 $parentTable = DiscussHelper::getTable( 'Post' );
2151 $parentTable->load( $parent );
2152
2153 $emailPostTitle = $parentTable->title;
2154
2155 $oriPostAuthor = $parentTable->user_id;
2156
2157 if( !$parentTable->user_id )
2158 {
2159 $ownerEmails[] = $parentTable->poster_email;
2160 }
2161 else
2162 {
2163 $oriPostUser = JFactory::getUser( $oriPostAuthor );
2164 $ownerEmails[] = $oriPostUser->email;
2165 }
2166 }
2167
2168 $emailSubject = ( empty( $parent ) ) ? JText::sprintf('COM_EASYDISCUSS_NEW_POST_ADDED', $post->id , $emailPostTitle ) : JText::sprintf( 'COM_EASYDISCUSS_NEW_REPLY_ADDED', $parent, $emailPostTitle );
2169 $emailTemplate = ( empty( $parent ) ) ? 'email.subscription.site.new.php' : 'email.post.reply.new.php';
2170
2171 //get all site's subscribers email that want to receive notification immediately
2172 $subscriberEmails = array();
2173 $subscribers = array();
2174
2175
2176 // @rule: Specify the default name and avatar
2177 $authorName = $post->poster_name;
2178 $authorAvatar = DISCUSS_JURIROOT . '/media/com_easydiscuss/images/default_avatar.png';
2179
2180
2181
2182 // @rule: Only process author items that belongs to a valid user.
2183 if (!empty($postOwner)) {
2184 $user = ED::user($postOwner);
2185
2186 $authorName = $user->getName();
2187 $authorAvatar = $user->getAvatar();
2188 }
2189
2190 if( $config->get('main_sitesubscription') && ($isNew || $prevPostStatus == DISCUSS_ID_PENDING) )
2191 {
2192 $subscribers = $modelSubscribe->getSiteSubscribers('instant','',$post->category_id);
2193 $postSubscribers = $modelSubscribe->getPostSubscribers( $post->parent_id );
2194
2195 // This was added because the user allow site wide notification (as in all subscribers should get notified) but category subscribers did not get it.
2196 $catSubscribers = $modelSubscribe->getCategorySubscribers( $post->id );
2197
2198 if(! empty($subscribers))
2199 {
2200 foreach($subscribers as $subscriber)
2201 {
2202 $subscriberEmails[] = $subscriber->email;
2203 }
2204 }
2205 if(! empty($postSubscribers))
2206 {
2207 foreach($postSubscribers as $postSubscriber)
2208 {
2209 $postSubscriberEmails[] = $postSubscriber->email;
2210 }
2211 }
2212 if(! empty($catSubscribers))
2213 {
2214 foreach($catSubscribers as $catSubscriber)
2215 {
2216 $catSubscriberEmails[] = $catSubscriber->email;
2217 }
2218 }
2219 }
2220
2221
2222 // Notify Participants if this is a reply
2223 if( !empty( $parent ) && $config->get( 'notify_participants' ) && ($isNew || $prevPostStatus == DISCUSS_ID_PENDING) )
2224 {
2225 $participantEmails = DiscussHelper::getHelper( 'Mailer' )->_getParticipants( $post->parent_id );
2226
2227 $participantEmails = array_unique( $participantEmails );
2228
2229 // merge into owneremails. dirty hacks.
2230 if( count( $participantEmails ) > 0 )
2231 {
2232 $newPostOwnerEmails = array_merge( $newPostOwnerEmails, $participantEmails );
2233 }
2234 }
2235
2236
2237 if( !empty( $adminEmails ) || !empty( $subscriberEmails ) || !empty( $newPostOwnerEmails ) || !empty( $postSubscriberEmails ) || $config->get( 'notify_all' ) )
2238 {
2239 $emails = array_unique(array_merge($adminEmails, $subscriberEmails, $newPostOwnerEmails, $postSubscriberEmails, $catSubscriberEmails));
2240
2241 // prepare email content and information.
2242 $emailData = array();
2243 $emailData['postTitle'] = $emailPostTitle;
2244 $emailData['postAuthor'] = $authorName;
2245 $emailData['postAuthorAvatar'] = $authorAvatar;
2246 $emailData['replyAuthor'] = $authorName;
2247 $emailData['replyAuthorAvatar'] = $authorAvatar;
2248 $emailData['comment'] = $post->content;
2249 $emailData['postContent' ] = $post->trimEmail( $post->content );
2250 $emailData['replyContent'] = $post->trimEmail( $post->content );
2251
2252 $attachments = $post->getAttachments();
2253 $emailData['attachments'] = $attachments;
2254
2255 // get the correct post id in url, the parent post id should take precedence
2256 $postId = empty( $parent ) ? $post->id : $parentTable->id;
2257
2258 $emailData['postLink'] = DiscussRouter::getRoutedURL('index.php?option=com_easydiscuss&view=post&id=' . $postId, false, true);
2259
2260 if( $config->get( 'notify_all' ) && $post->published == DISCUSS_ID_PUBLISHED )
2261 {
2262 $emailData['emailTemplate'] = 'email.subscription.site.new.php';
2263 $emailData['emailSubject'] = JText::sprintf('COM_EASYDISCUSS_NEW_QUESTION_ASKED', $post->id , $post->title);
2264 DiscussHelper::getHelper( 'Mailer' )->notifyAllMembers( $emailData, $newPostOwnerEmails );
2265 }
2266 else
2267 {
2268 //insert into mailqueue
2269 foreach ($emails as $email)
2270 {
2271
2272 if ( in_array($email, $subscriberEmails) || in_array($email, $postSubscriberEmails) || in_array($email, $newPostOwnerEmails) )
2273 {
2274 $doContinue = false;
2275
2276 // these are subscribers
2277 if (!empty($subscribers))
2278 {
2279 foreach ($subscribers as $key => $value)
2280 {
2281 if ($value->email == $email)
2282 {
2283 $emailData['unsubscribeLink'] = DiscussHelper::getUnsubscribeLink( $subscribers[$key], true, true);
2284 $notify->addQueue($email, $emailSubject, '', $emailTemplate, $emailData);
2285 $doContinue = true;
2286 break;
2287 }
2288 }
2289 }
2290
2291 if( $doContinue )
2292 continue;
2293
2294 if (!empty($postSubscribers))
2295 {
2296
2297 foreach ($postSubscribers as $key => $value)
2298 {
2299 if ($value->email == $email)
2300 {
2301
2302 $emailData['unsubscribeLink'] = DiscussHelper::getUnsubscribeLink( $postSubscribers[$key], true, true);
2303 $notify->addQueue($email, $emailSubject, '', $emailTemplate, $emailData);
2304 $doContinue = true;
2305 break;
2306 }
2307 }
2308 }
2309
2310 if( $doContinue )
2311 continue;
2312
2313
2314 if (!empty($newPostOwnerEmails))
2315 {
2316
2317 $emailSubject = JText::sprintf( 'COM_EASYDISCUSS_NEW_POST_ADDED', $emailPostTitle, $post->id );
2318
2319 foreach ($newPostOwnerEmails as $ownerEmail)
2320 {
2321
2322 //$emailData['unsubscribeLink'] = DiscussHelper::getUnsubscribeLink( $ownerEmail, true, true);
2323 $notify->addQueue($email, $emailSubject, '', $emailTemplate, $emailData);
2324 $doContinue = true;
2325 break;
2326 }
2327 }
2328
2329 }
2330 else
2331 {
2332
2333 // non-subscribers will not get the unsubscribe link
2334 $notify->addQueue($email, $emailSubject, '', $emailTemplate, $emailData);
2335 }
2336 }
2337 }
2338 }
2339 }
2340
2341 public static function getUserRepliesHTML( $postId, $excludeLastReplyUser = false)
2342 {
2343 $model = ED::model( 'Posts' );
2344 $replies = $model->getUserReplies($postId, $excludeLastReplyUser);
2345
2346 $html = '';
2347 if( !empty( $replies ) )
2348 {
2349 $tpl = new DiscussThemes();
2350 $tpl->set( 'replies' , $replies );
2351 $html = $tpl->fetch( 'main.item.replies.php' );
2352 }
2353
2354 return $html;
2355 }
2356
2357 public static function getUserAcceptedReplyHTML( $postId )
2358 {
2359 $model = JED::model( 'Posts' );
2360 $reply = $model->getAcceptedReply( $postId );
2361
2362 $html = '';
2363 if( ! empty( $reply ) )
2364 {
2365 $tpl = new DiscussThemes();
2366 $tpl->set( 'reply' , $reply );
2367 $html = $tpl->fetch( 'main.item.answered.php' );
2368 }
2369
2370 return $html;
2371 }
2372
2373 public static function isSiteSubscribed( $userId )
2374 {
2375 if( !class_exists( 'EasyDiscussModelSubscribe') )
2376 {
2377 jimport( 'joomla.application.component.model' );
2378 JLoader::import( 'subscribe' , DISCUSS_MODELS );
2379 }
2380 $model = ED::model( 'Subscribe' );
2381
2382 $user = JFactory::getUser( $userId );
2383
2384 $subscription = array();
2385 $subscription['type'] = 'site';
2386 $subscription['email'] = $user->email;
2387 $subscription['cid'] = 0;
2388
2389 $result = $model->isSiteSubscribed( $subscription );
2390
2391 return ( !isset($result['id']) ) ? '0' : $result['id'];
2392 }
2393
2394 public static function isPostSubscribed( $userId, $postId )
2395 {
2396 $model = ED::model( 'Subscribe' );
2397
2398 $user = JFactory::getUser( $userId );
2399
2400 $subscription = array();
2401 $subscription['type'] = 'post';
2402 $subscription['userid'] = $user->id;
2403 $subscription['email'] = $user->email;
2404 $subscription['cid'] = $postId;
2405
2406 $result = $model->isPostSubscribedEmail( $subscription );
2407
2408 return ( !isset($result['id']) ) ? '0' : $result['id'];
2409 }
2410
2411 public static function isMySubscription( $userid, $type, $subId)
2412 {
2413 $model = ED::model( 'Subscribe' );
2414 return $model->isMySubscription($userid, $type, $subId);
2415 }
2416
2417 public static function hasPassword( $post )
2418 {
2419 $session = JFactory::getSession();
2420 $password = $session->get( 'DISCUSSPASSWORD_' . $post->id , '' , 'com_easydiscuss' );
2421
2422 if( $password == $post->password )
2423 {
2424 return true;
2425 }
2426 return false;
2427 }
2428
2429 public static function getUserComponent()
2430 {
2431 return ( DiscussHelper::getJoomlaVersion() >= '1.6' ) ? 'com_users' : 'com_user';
2432 }
2433
2434 public static function getUserComponentLoginTask()
2435 {
2436 return ( DiscussHelper::getJoomlaVersion() >= '1.6' ) ? 'user.login' : 'login';
2437 }
2438
2439 public static function getAccessibleCategories( $parentId = 0, $type = DISCUSS_CATEGORY_ACL_ACTION_VIEW, $customUserId = '' )
2440 {
2441 static $accessibleCategories = array();
2442
2443 if( !empty($customUserId) )
2444 {
2445 $my = JFactory::getUser( $customUserId );
2446 }
2447 else
2448 {
2449 $my = JFactory::getUser();
2450 }
2451
2452 // $sig = serialize( array($type, $my->id, $parentId) );
2453
2454 $sig = (int) $my->id . '-' . (int) $parentId . '-' . (int) $type;
2455
2456
2457 //if( !array_key_exists($sig, $accessibleCategories) )
2458 if(! isset( $accessibleCategories[$sig] ) )
2459 {
2460
2461 $db = DiscussHelper::getDBO();
2462
2463 $gids = '';
2464 $catQuery = 'select distinct a.`id`, a.`private`';
2465 $catQuery .= ' from `#__discuss_category` as a';
2466
2467
2468 if( $my->id == 0 )
2469 {
2470 $catQuery .= ' where (a.`private` = ' . $db->Quote('0') . ' OR ';
2471 }
2472 else
2473 {
2474 $catQuery .= ' where (a.`private` = ' . $db->Quote('0') . ' OR a.`private` = ' . $db->Quote('1') . ' OR ';
2475 }
2476
2477
2478 $gid = array();
2479 $gids = '';
2480
2481 if( DiscussHelper::getJoomlaVersion() >= '1.6' )
2482 {
2483 $gid = array();
2484 if( $my->id == 0 )
2485 {
2486 $gid = JAccess::getGroupsByUser(0, false);
2487 }
2488 else
2489 {
2490 $gid = JAccess::getGroupsByUser($my->id, false);
2491 }
2492 }
2493 else
2494 {
2495 $gid = DiscussHelper::getUserGids();
2496 }
2497
2498
2499 if( count( $gid ) > 0 )
2500 {
2501 foreach( $gid as $id)
2502 {
2503 $gids .= ( empty($gids) ) ? $db->Quote( $id ) : ',' . $db->Quote( $id );
2504 }
2505
2506 $catQuery .= ' a.`id` IN (';
2507 $catQuery .= ' select b.`category_id` from `#__discuss_category_acl_map` as b';
2508 $catQuery .= ' where b.`category_id` = a.`id` and b.`acl_id` = '. $db->Quote( $type );
2509 $catQuery .= ' and b.`type` = ' . $db->Quote('group');
2510 $catQuery .= ' and b.`content_id` IN (' . $gids . ')';
2511
2512 //logged in user
2513 if( $my->id != 0 )
2514 {
2515 $catQuery .= ' union ';
2516 $catQuery .= ' select b.`category_id` from `#__discuss_category_acl_map` as b';
2517 $catQuery .= ' where b.`category_id` = a.`id` and b.`acl_id` = ' . $db->Quote( $type );
2518 $catQuery .= ' and b.`type` = ' . $db->Quote('user');
2519 $catQuery .= ' and b.`content_id` = ' . $db->Quote( $my->id );
2520 }
2521 $catQuery .= ')';
2522
2523 }
2524
2525 $catQuery .= ')';
2526 $catQuery .= ' AND a.parent_id = ' . $db->Quote($parentId);
2527
2528 $db->setQuery($catQuery);
2529 $result = $db->loadObjectList();
2530
2531 $accessibleCategories[ $sig ] = $result;
2532
2533 }
2534
2535 return $accessibleCategories[ $sig ];
2536 }
2537
2538 public static function getPrivateCategories( $acltype = DISCUSS_CATEGORY_ACL_ACTION_VIEW )
2539 {
2540 $db = DiscussHelper::getDBO();
2541 $my = JFactory::getUser();
2542 static $result = array();
2543
2544 $excludeCats = array();
2545
2546 $sig = (int) $my->id . '-' . (int) $acltype;
2547
2548 if(! isset( $result[ $sig ] ) )
2549 {
2550 if($my->id == 0)
2551 {
2552 $catQuery = 'select distinct a.`id`, a.`private`';
2553 $catQuery .= ' from `#__discuss_category` as a';
2554 $catQuery .= ' left join `#__discuss_category_acl_map` as b on a.`id` = b.`category_id`';
2555 $catQuery .= ' and b.`acl_id` = ' . $db->Quote( $acltype );
2556 $catQuery .= ' and b.`type` = ' . $db->Quote( 'group' );
2557 $catQuery .= ' where a.`private` != ' . $db->Quote('0');
2558
2559 $gid = array();
2560 $gids = '';
2561
2562
2563 if( DiscussHelper::getJoomlaVersion() >= '1.6' )
2564 {
2565 // $gid = JAccess::getGroupsByUser(0, false);
2566
2567 $gid = DiscussHelper::getUserGroupId($my);
2568 }
2569 else
2570 {
2571 $gid = DiscussHelper::getUserGids();
2572 }
2573
2574 if( count( $gid ) > 0 )
2575 {
2576 foreach( $gid as $id)
2577 {
2578 $gids .= ( empty($gids) ) ? $db->Quote( $id ) : ',' . $db->Quote( $id );
2579 }
2580 $catQuery .= ' and a.`id` NOT IN (';
2581 $catQuery .= ' SELECT c.category_id FROM `#__discuss_category_acl_map` as c ';
2582 $catQuery .= ' WHERE c.acl_id = ' .$db->Quote( $acltype );
2583 $catQuery .= ' AND c.type = ' . $db->Quote('group');
2584 $catQuery .= ' AND c.content_id IN (' . $gids . ') )';
2585 }
2586
2587 $db->setQuery($catQuery);
2588 $result = $db->loadObjectList();
2589 }
2590 else
2591 {
2592 $result = ED::getAclCategories ( $acltype, $my->id );
2593 }
2594
2595 for($i=0; $i < count($result); $i++)
2596 {
2597 $item =& $result[$i];
2598 $item->childs = null;
2599
2600 DiscussHelper::buildNestedCategories($item->id, $item, true);
2601
2602 $catIds = array();
2603 $catIds[] = $item->id;
2604 DiscussHelper::accessNestedCategoriesId($item, $catIds);
2605
2606 $excludeCats = array_merge($excludeCats, $catIds);
2607 }
2608
2609 $result[ $sig ] = $excludeCats;
2610 }
2611
2612 return $result[ $sig ];
2613 }
2614
2615 public static function getAclCategories ($type = DISCUSS_CATEGORY_ACL_ACTION_VIEW, $userId = '', $parentId = false)
2616 {
2617 static $categories = array();
2618
2619 //$sig = serialize( array($type, $userId, $parentId) );
2620 $sig = (int) $type . '-' . (int) $userId . '-' . (int) $parentId;
2621
2622 //if( !array_key_exists($sig, $categories) )
2623 if (!isset($categories[$sig])) {
2624 $db = ED::db();
2625 $gid = JAccess::getGroupsByUser($userId, false);
2626
2627 if (ED::getJoomlaVersion() >= '1.6') {
2628 if ($userId == '') {
2629 $gid = JAccess::getGroupsByUser(0, false);
2630 } else {
2631 $gid = JAccess::getGroupsByUser($userId, false);
2632 }
2633 }
2634
2635 $gids = '';
2636 if (count($gid) > 0) {
2637 $gids = implode( ',', $gid );
2638 }
2639
2640 $query = 'select c.`id` from `#__discuss_category` as c';
2641 $query .= ' where not exists (';
2642 $query .= ' select b.`category_id` from `#__discuss_category_acl_map` as b';
2643 $query .= ' where b.`category_id` = c.`id` and b.`acl_id` = '. $db->Quote($type);
2644 $query .= ' and b.`type` = ' . $db->Quote('group');
2645 $query .= ' and b.`content_id` IN (' . $gids . ')';
2646
2647 $query .= ' )';
2648 $query .= ' and c.`private` = ' . $db->Quote(DISCUSS_PRIVACY_ACL);
2649 if( $parentId !== false )
2650 $query .= ' and c.`parent_id` = ' . $db->Quote($parentId);
2651
2652 $db->setQuery($query);
2653
2654 $categories[$sig] = $db->loadObjectList();
2655 }
2656
2657 return $categories[$sig];
2658 }
2659
2660 /**
2661 * Renders a JTable object
2662 *
2663 * @since 4.0
2664 * @access public
2665 * @param string
2666 * @return
2667 */
2668 public static function table($name, $prefix = 'Discuss', $config = array())
2669 {
2670 // Sanitize and prepare the table class name.
2671 $type = preg_replace('/[^A-Z0-9_\.-]/i', '', $name);
2672 $className = $prefix . ucfirst($type);
2673
2674 // Only try to load the class if it doesn't already exist.
2675 if (!class_exists($className)) {
2676
2677 // Search for the class file in the JTable include paths.
2678 $path = DISCUSS_TABLES . '/' . strtolower($type) . '.php';
2679
2680 // Import the class file.
2681 include_once($path);
2682 }
2683
2684 return JTable::getInstance($type, $prefix, $config);
2685 }
2686
2687 /**
2688 * Retrieves the model
2689 *
2690 * @since 4.0
2691 * @access public
2692 * @param string The model's name.
2693 * @return mixed
2694 */
2695 public static function model($name)
2696 {
2697 static $models = array();
2698
2699 $key = $name;
2700
2701 if (!isset($models[$key])) {
2702
2703 $file = strtolower($name) . '.php';
2704
2705 $path = DISCUSS_MODELS . '/' . $file;
2706
2707 if (!JFile::exists($path)) {
2708 return JError::raiseWarning(500, JText::sprintf('Requested model %1$s is not found.', $file));
2709 }
2710
2711 $className = 'EasyDiscussModel' . ucfirst($name);
2712
2713 if (!class_exists($className)) {
2714 require_once($path);
2715 }
2716
2717 $models[$key] = new $className();
2718 }
2719
2720 return $models[$key];
2721 }
2722
2723 /**
2724 * Retrieves the pagination object
2725 *
2726 * @since 4.0
2727 * @access public
2728 * @param string
2729 * @return
2730 */
2731 public static function getPagination($total, $limitstart, $limit, $prefix = '')
2732 {
2733 static $instances;
2734
2735 if (!isset($instances)) {
2736 $instances = array();
2737 }
2738
2739 $signature = serialize(array($total, $limitstart, $limit, $prefix));
2740
2741 if (empty($instances[$signature])) {
2742 $pagination = ED::pagination($total, $limitstart, $limit, $prefix);
2743
2744 $instances[$signature] = $pagination;
2745 }
2746
2747 return $instances[$signature];
2748 }
2749
2750 /**
2751 * Retrieve @JUser object based on the given email address.
2752 *
2753 * @access public
2754 * @param string $email The user's email address.
2755 * @return JUser @JUser object.
2756 **/
2757 public static function getUserByEmail( $email )
2758 {
2759 $email = strtolower( $email );
2760
2761 $db = DiscussHelper::getDBO();
2762
2763 $query = 'SELECT ' . $db->nameQuote( 'id' ) . ' FROM '
2764 . $db->nameQuote( '#__users' ) . ' '
2765 . 'WHERE LOWER(' . $db->nameQuote( 'email' ) . ') = ' . $db->Quote( $email );
2766 $db->setQuery( $query );
2767 $id = $db->loadResult();
2768
2769 if( !$id )
2770 {
2771 return false;
2772 }
2773
2774 return JFactory::getUser( $id );
2775 }
2776
2777 public static function getUserGids( $userId = '' )
2778 {
2779 $userId = empty($userId) ? null : $userId;
2780 $user = JFactory::getUser($userId);
2781
2782 $groups = JAccess::getGroupsByUser($user->id);
2783 $ids = array();
2784
2785 foreach ($groups as $group) {
2786 $ids[] = $group;
2787 }
2788
2789 return $ids;
2790 }
2791
2792 public static function getJoomlaUserGroups( $cid = '' )
2793 {
2794 $db = DiscussHelper::getDBO();
2795
2796 if(ED::getJoomlaVersion() >= '1.6')
2797 {
2798 $query = 'SELECT a.id, a.title AS `name`, COUNT(DISTINCT b.id) AS level';
2799 $query .= ' , GROUP_CONCAT(b.id SEPARATOR \',\') AS parents';
2800 $query .= ' FROM #__usergroups AS a';
2801 $query .= ' LEFT JOIN `#__usergroups` AS b ON a.lft > b.lft AND a.rgt < b.rgt';
2802 }
2803 else
2804 {
2805 $query = 'SELECT `id`, `name`, 0 as `level` FROM ' . $db->nameQuote('#__core_acl_aro_groups') . ' a ';
2806 }
2807
2808 // Condition
2809 $where = array();
2810
2811 // We need to filter out the ROOT and USER dummy records.
2812 if(ED::getJoomlaVersion() < '1.6')
2813 {
2814 $where[] = '(a.`id` > 17 AND a.`id` < 26)';
2815 }
2816
2817 if( !empty( $cid ) )
2818 {
2819 $where[] = ' a.`id` = ' . $db->quote($cid);
2820 }
2821 $where = ( count( $where ) ? ' WHERE ' .implode( ' AND ', $where ) : '' );
2822
2823 $query .= $where;
2824
2825 // Grouping and ordering
2826 if( ED::getJoomlaVersion() >= '1.6' )
2827 {
2828 $query .= ' GROUP BY a.id';
2829 $query .= ' ORDER BY a.lft ASC';
2830 }
2831 else
2832 {
2833 $query .= ' ORDER BY a.id';
2834 }
2835
2836 $db->setQuery( $query );
2837 $result = $db->loadObjectList();
2838
2839 if( DiscussHelper::getJoomlaVersion() < '1.6' )
2840 {
2841 $guest = new stdClass();
2842 $guest->id = '0';
2843 $guest->name = 'Public';
2844 $guest->level = '0';
2845 array_unshift( $result, $guest );
2846 }
2847
2848 return $result;
2849 }
2850
2851 public static function getUnsubscribeLink($subdata, $external = false, $html = false)
2852 {
2853 $unsubdata = base64_encode("type=".$subdata->type."\r\nsid=".$subdata->id."\r\nuid=".$subdata->userid."\r\ntoken=".md5($subdata->id.$subdata->created));
2854
2855 $link = EDR::getRoutedURL('index.php?option=com_easydiscuss&controller=subscription&task=unsubscribe&data='.$unsubdata, false, $external);
2856
2857 return $link;
2858 }
2859
2860 /*
2861 * Return class name according to user's group.
2862 * e.g. 'reply-usergroup-1 reply-usergroup-2'
2863 *
2864 */
2865 public static function userToClassname($jUserObj, $classPrefix = 'reply', $delimiter = '-')
2866 {
2867 if (is_numeric($jUserObj))
2868 {
2869 $jUserObj = JFactory::getUser($jUserObj);
2870 }
2871
2872 if( !$jUserObj instanceof JUser )
2873 {
2874 return '';
2875 }
2876
2877 static $classNames;
2878
2879 if (!isset($classNames))
2880 {
2881 $classNames = array();
2882 }
2883
2884 $signature = serialize(array($jUserObj->id, $classPrefix, $delimiter));
2885
2886 if (!isset($classNames[$signature]))
2887 {
2888 $classes = array();
2889
2890 $classes[] = $classPrefix . $delimiter . 'user' . $delimiter . $jUserObj->id;
2891
2892 if (property_exists($jUserObj, 'gid'))
2893 {
2894 $classes[] = $classPrefix . $delimiter . 'usergroup' . $delimiter . $jUserObj->get( 'gid' );
2895 }
2896 else
2897 {
2898 $groups = $jUserObj->getAuthorisedGroups();
2899
2900 foreach($groups as $id)
2901 {
2902 $classes[] = $classPrefix . $delimiter . 'usergroup' . $delimiter . $id;
2903 }
2904 }
2905
2906 $classNames[$signature] = implode(' ', $classes);
2907 }
2908
2909 return $classNames[$signature];
2910 }
2911
2912 /**
2913 * Ensures that the user is logged in
2914 *
2915 * @since 4.0
2916 * @access public
2917 * @param string
2918 * @return
2919 */
2920 public static function requireLogin()
2921 {
2922 $app = JFactory::getApplication();
2923 $user = JFactory::getUser();
2924
2925 if ($user->guest) {
2926
2927 // Set the callback so it can be use later.
2928 $currentUrl = EDR::current();
2929 ED::setCallback($currentUrl);
2930
2931 ED::setMessageQueue(JText::_( 'COM_EASYDISCUSS_SIGNIN_PLEASE_LOGIN' ), 'info');
2932 return $app->redirect(EDR::_('view=login', false));
2933 }
2934 }
2935
2936 /**
2937 * Give a proper redirection when the user does not have the permission to view the item.
2938 *
2939 * @since 4.0
2940 * @access public
2941 * @param string
2942 * @return
2943 */
2944 public static function getErrorRedirection($message = null)
2945 {
2946 $config = ED::config();
2947 $app = JFactory::getApplication();
2948 $user = JFactory::getUser();
2949
2950 if (!$message) {
2951 $message = JText::_('COM_EASYDISCUSS_SYSTEM_INSUFFICIENT_PERMISSIONS');
2952 }
2953
2954 $redirection = $config->get('system_error_redirection', true);
2955
2956 if ($redirection) {
2957
2958 // If user haven't logged in, redirect them to login page.
2959 ED::requireLogin();
2960
2961 // If it reached here means the user is already logged in.
2962 ED::setMessageQueue($message, 'error');
2963 return $app->redirect(EDR::_('view=index'), false);
2964 }
2965
2966 // default redirection
2967 return JError::raiseError(404, $message);
2968 }
2969
2970 /**
2971 * Retrieve similar question based on the keywords
2972 *
2973 * @access public
2974 * @param string $keywords
2975 */
2976 public static function getSimilarQuestion( $text = '' )
2977 {
2978
2979 $config = ED::config();
2980
2981 if (empty($text)) {
2982 return '';
2983 }
2984
2985 if (! $config->get('main_similartopic', 0)){
2986 return '';
2987 }
2988
2989
2990 $options = array();
2991 $options['limi'] = $config->get('main_similartopic_limit', '5');
2992 $options['includePrivatePost'] = $config->get('main_similartopic_privatepost', 0);
2993
2994 $model = ED::model('Posts');
2995 $posts = $model->getSimilarQuestion($text, $options);
2996
2997 if ($posts) {
2998 //preload posts
2999 $posts = ED::formatPost($posts);
3000 }
3001
3002 return $posts;
3003
3004 }
3005
3006 /**
3007 * Retrieves the html block for board statistics.
3008 *
3009 * @since 3.0
3010 * @access public
3011 */
3012 public static function getBoardStatistics()
3013 {
3014 $config = ED::config();
3015 $allowed = true;
3016 $disallowedGroups = $config->get('main_exclude_frontend_statistics');
3017
3018 if (!$config->get('main_frontend_statistics')) {
3019 return;
3020 }
3021
3022 if (!empty($disallowedGroups)) {
3023
3024 //Remove whitespace
3025 $disallowedGroups = trim($disallowedGroups);
3026 $disallowedGroups = explode(',', $disallowedGroups);
3027
3028 $my = JFactory::getUser();
3029 $groups = $my->groups;
3030
3031 $result = array_intersect($groups, $disallowedGroups);
3032
3033 $allowed = !$result ? true : false;
3034 }
3035
3036 if (!$allowed) {
3037 return;
3038 }
3039
3040 $theme = ED::themes();
3041
3042 $postModel = ED::model('Posts');
3043 $totalPosts = $postModel->getTotal();
3044
3045 $resolvedPosts = $postModel->getTotalResolved();
3046 $unresolvedPosts = $postModel->getUnresolvedCount();
3047
3048 $userModel = ED::model('Users');
3049 $totalUsers = $userModel->getTotalUsers();
3050
3051
3052 $ids = $userModel->getLatestUser();
3053 $latestMember = ED::user($ids);
3054
3055 // Total guests
3056 $totalGuests = $userModel->getTotalGuests();
3057
3058 // Online users
3059 $onlineUsers = $userModel->getOnlineUsers();
3060
3061 $theme->set('latestMember', $latestMember);
3062 $theme->set('unresolvedPosts', $unresolvedPosts);
3063 $theme->set('resolvedPosts', $resolvedPosts);
3064 $theme->set('totalUsers', $totalUsers);
3065 $theme->set('totalPosts', $totalPosts);
3066 $theme->set('onlineUsers', $onlineUsers);
3067 $theme->set('totalGuests', $totalGuests);
3068
3069 return $theme->output('site/frontpage/stats');
3070 }
3071
3072 /**
3073 * Method to retrieve a EasyBlogUser object
3074 *
3075 * @since 1.0
3076 * @access public
3077 * @param null
3078 * @return SocialUser The user's object
3079 */
3080 public static function user( $ids = null , $debug = false )
3081 {
3082 $path = JPATH_ADMINISTRATOR . '/components/com_easydiscuss/includes/user/user.php';
3083 include_once($path);
3084
3085 return EasyDiscussUser::factory($ids, $debug);
3086 }
3087
3088 /**
3089 * Retrieve the html block for who's viewing this page.
3090 *
3091 * @access public
3092 * @param string $url
3093 */
3094 public static function getWhosOnline($uri = '')
3095 {
3096 $config = ED::config();
3097 $enabled = $config->get('main_viewingpage');
3098
3099 if (!$enabled) {
3100 return;
3101 }
3102
3103 // Default hash
3104 $hash = md5(JRequest::getURI());
3105
3106 if (!empty($uri)) {
3107 $hash = md5($uri);
3108 }
3109
3110 $model = ED::model('Users');
3111 $users = $model->getPageViewers($hash);
3112
3113 if (!$users) {
3114 return;
3115 }
3116
3117 $theme = ED::themes();
3118 $theme->set('users', $users);
3119
3120 return $theme->output('site/post/default.viewers');
3121 }
3122
3123 public static function getListLimit()
3124 {
3125 $app = JFactory::getApplication();
3126 $default = ED::jconfig()->get( 'list_limit' );
3127
3128 if( $app->isAdmin() )
3129 {
3130 return $default;
3131 }
3132
3133 $app = JFactory::getApplication();
3134 $menus = $app->getMenu();
3135 $menu = $menus->getActive();
3136 $limit = -2;
3137
3138 if( is_object( $menu ) )
3139 {
3140 $params = DiscussHelper::getRegistry( $menu->params );
3141 $limit = $params->get( 'limit' , '-2' );
3142 }
3143
3144 if( $limit == '-2' )
3145 {
3146 // Use default configurations.
3147 $config = DiscussHelper::getConfig();
3148 $limit = $config->get( 'layout_list_limit', '-2' );
3149 }
3150
3151 // Revert to joomla's pagination if configured to inherit from Joomla
3152 if( $limit == '0' || $limit == '-1' || $limit == '-2' )
3153 {
3154 $limit = $default;
3155 }
3156
3157 return $limit;
3158 }
3159
3160 public static function getRegistrationLink()
3161 {
3162 $config = DiscussHelper::getConfig();
3163
3164 $default = JRoute::_( 'index.php?option=com_user&view=register' );
3165 if( DiscussHelper::getJoomlaVersion() >= '1.6' )
3166 {
3167 $default = JRoute::_( 'index.php?option=com_users&view=registration' );
3168 }
3169
3170 switch( $config->get( 'main_login_provider' ) )
3171 {
3172 case 'joomla':
3173 $link = $default;
3174 break;
3175
3176 case 'cb':
3177 $link = JRoute::_( 'index.php?option=com_comprofiler&task=registers' );
3178 break;
3179
3180 case 'easysocial':
3181
3182 if (ED::easysocial()->exists()) {
3183 $link = FRoute::registration();
3184 } else {
3185 $link = $default;
3186 }
3187
3188 break;
3189
3190 case 'jomsocial':
3191 $link = JRoute::_( 'index.php?option=com_community&view=register' );
3192 $file = JPATH_ROOT . '/components/com_community/libraries/core.php';
3193
3194 if (JFile::exists($file)) {
3195 require_once( $file );
3196 $link = CRoute::_( 'index.php?option=com_community&view=register' );
3197 }
3198 break;
3199 }
3200
3201 return $link;
3202 }
3203
3204 public static function getEditProfileLink()
3205 {
3206 $config = ED::config();
3207
3208 $link = EDR::_('view=profile&layout=edit');
3209
3210 if ($config->get('integration_easysocial_toolbar_profile')) {
3211 $easysocial = ED::easysocial();
3212
3213 if ($easysocial->exists()) {
3214 $link = FRoute::profile(array('layout' => 'edit'));
3215 }
3216 }
3217
3218 return $link;
3219 }
3220
3221 public static function getResetPasswordLink()
3222 {
3223 $config = DiscussHelper::getConfig();
3224
3225 $default = JRoute::_( 'index.php?option=com_user&view=reset' );
3226
3227 if( DiscussHelper::getJoomlaVersion() >= '1.6' )
3228 {
3229 $default = JRoute::_( 'index.php?option=com_users&view=reset' );
3230 }
3231
3232
3233 switch( $config->get( 'main_login_provider' ) )
3234 {
3235 case 'easysocial':
3236
3237 if (ED::easysocial()->exists()) {
3238 $link = FRoute::profile( array( 'layout' => 'forgetPassword' ) );
3239 } else {
3240 $link = $default;
3241 }
3242 break;
3243 case 'joomla':
3244 case 'cb':
3245 case 'jomsocial':
3246 default:
3247 $link = $default;
3248 break;
3249 }
3250
3251 return $link;
3252 }
3253
3254 public static function getDefaultRepliesSorting()
3255 {
3256 $config = ED::config();
3257 $defaultFilter = $config->get('layout_replies_sorting');
3258
3259 if ($defaultFilter == 'voted' && !$config->get('main_allowvote')) {
3260 $defaultFilter = 'oldest';
3261 }
3262
3263 if ($defaultFilter == 'likes' && !$config->get('main_likes_replies')) {
3264 $defaultFilter = 'oldest';
3265 }
3266
3267 return $defaultFilter;
3268 }
3269
3270 /**
3271 * Allows caller to set the page title.
3272 *
3273 * @since 4.0
3274 * @access public
3275 * @param string
3276 * @return
3277 */
3278 public static function setPageTitle($text = '', $pagination = null)
3279 {
3280 $text = JText::_($text);
3281
3282 // now check if site name is needed or not.
3283 $app = JFactory::getApplication();
3284 $doc = JFactory::getDocument();
3285
3286 $app = JFactory::getApplication();
3287 $itemid = $app->input->get('Itemid', '');
3288
3289 $menu = JFactory::getApplication()->getMenu();
3290 $item = $menu->getItem($itemid);
3291
3292 if (is_object($item)) {
3293
3294 $params = $item->params;
3295
3296 if (!$params instanceof JRegistry) {
3297 $params = new JRegistry($item->params);
3298 }
3299
3300 $customPageTitle = $params->get('page_title', '');
3301
3302 if ($customPageTitle) {
3303 $text = $customPageTitle;
3304 }
3305 }
3306
3307
3308 // Prepare Joomla's site title if necessary.
3309 $jConfig = ED::jConfig();
3310 $addTitle = $jConfig->get('sitename_pagetitles');
3311
3312 // Only add Joomla's site title if it was configured to.
3313 if ($addTitle) {
3314
3315 $siteTitle = $jConfig->get('sitename');
3316
3317 if ($addTitle == 1) {
3318 $text = $siteTitle . ' - ' . $text;
3319 }
3320
3321 if ($addTitle == 2) {
3322 $text = $text . ' - ' . $siteTitle;
3323 }
3324 }
3325
3326 if ($pagination) {
3327 $paginationNumber = $pagination->getPageNumber();
3328
3329 if ($paginationNumber > 1) {
3330 $paginationText = JText::sprintf('COM_EASYDISCUSS_PAGINATION_TEXT', $paginationNumber);
3331 $text = $text . ' - ' . $paginationText;
3332 }
3333 }
3334
3335 $doc->setTitle($text);
3336 }
3337
3338
3339 public static function setMeta()
3340 {
3341 $config = DiscussHelper::getConfig();
3342 $db = DiscussHelper::getDBO();
3343
3344
3345 $menu = JFactory::getApplication()->getMenu();
3346 $item = $menu->getActive();
3347
3348 $result = new stdClass();
3349 $result->description = $config->get( 'main_description' );
3350 $result->keywords = '';
3351
3352 $description = '';
3353
3354 if( is_object( $item ) )
3355 {
3356 $params = $item->params;
3357
3358 if(! $params instanceof JRegistry )
3359 {
3360 $params = DiscussHelper::getRegistry( $item->params );
3361 }
3362
3363 $description = $params->get( 'menu-meta_description' , '' );
3364 $keywords = $params->get( 'menu-meta_keywords' , '' );
3365
3366 if( ! empty ( $description ) )
3367 {
3368 $result->description = $description;
3369 }
3370
3371 if( ! empty ( $keywords ) )
3372 {
3373 $result->keywords = $keywords;
3374 }
3375 }
3376
3377 $document = JFactory::getDocument();
3378 if ( empty( $result->keywords ) && empty( $result->description ) )
3379 {
3380 // Get joomla default description.
3381 $jConfig = ED::jconfig();
3382 $joomlaDesc = $jConfig->get('MetaDesc');
3383
3384 $metaDesc = $description . ' - ' . $joomlaDesc;
3385 $document->setMetadata('description', $metaDesc);
3386 }
3387 else
3388 {
3389 if ( !empty( $result->keywords ) )
3390 {
3391 $document->setMetadata('keywords', $result->keywords);
3392 }
3393
3394 if ( !empty( $result->description ) )
3395 {
3396 $document->setMetadata('description', $result->description);
3397 }
3398 }
3399 } //end function setMeta
3400
3401 public static function getFrontpageCategories()
3402 {
3403 $catModel = ED::model( 'Categories' );
3404 $newPostCount = 0;
3405
3406 if( !$categories = $catModel->getCategories() )
3407 {
3408 return array();
3409 }
3410
3411 foreach ($categories as $category)
3412 {
3413 $postModel = ED::model( 'Posts' );
3414 $category->newCount = $postModel->getNewCount( '' , $category->id , null , false );
3415 $newPostCount += $category->newCount;
3416 }
3417
3418 // Temporary store in user state.
3419 $app = JFactory::getApplication();
3420 $app->setUserState( 'com_easydiscuss.helper.totalnewpost', $newPostCount );
3421
3422 return $categories;
3423 }
3424
3425 public static function log( $var = '', $force = 0 )
3426 {
3427 $debugroot = DISCUSS_HELPERS . '/debug';
3428
3429 $firephp = false;
3430 $chromephp = false;
3431
3432 if( JFile::exists( $debugroot . '/fb.php' ) && JFile::exists( $debugroot . '/FirePHP.class.php' ) )
3433 {
3434 include_once( $debugroot . '/fb.php' );
3435 fb( $var );
3436 }
3437
3438 if( JFile::exists( $debugroot . '/chromephp.php' ) )
3439 {
3440 include_once( $debugroot . '/chromephp.php' );
3441 ChromePhp::log( $var );
3442 }
3443 }
3444
3445 /**
3446 * Determines if the user is a moderator of the forum
3447 *
3448 * @since 4.0
3449 * @access public
3450 * @param string
3451 * @return
3452 */
3453 public static function isModerator($categoryId = null, $userId = null)
3454 {
3455 $moderator = ED::moderator()->isModerator($categoryId, $userId);
3456
3457 return $moderator;
3458 }
3459
3460 public static function getUserGroupId(JUser $user, $recursive = true)
3461 {
3462 $groups = JAccess::getGroupsByUser($user->id, $recursive);
3463
3464 return $groups;
3465 }
3466
3467 /**
3468 * Method determines if the content needs to be parsed through any parser or not.
3469 *
3470 * @since 3.0
3471 * @access public
3472 * @param string The content's string.
3473 */
3474 public static function parseContent( $content, $forceBBCode=false )
3475 {
3476 $config = ED::config();
3477
3478 $content = ED::string()->escape($content);
3479
3480 // Pass it to bbcode parser.
3481 $content = ED::parser()->bbcode( $content );
3482 $content = nl2br($content);
3483
3484 //Remove BR in pre tag
3485 $content = preg_replace_callback('/<pre.*?\>(.*?)<\/pre>/ims', array( 'EasyDiscussParser' , 'removeBr' ) , $content );
3486 $content = preg_replace_callback('/<ol.*?\>(.*?)<\/ol>/ims', array( 'EasyDiscussParser' , 'removeBr' ) , $content );
3487 $content = preg_replace_callback('/<ul.*?\>(.*?)<\/ul>/ims', array( 'EasyDiscussParser' , 'removeBr' ) , $content );
3488
3489 $content = str_ireplace("</pre><br />", '</pre>', $content);
3490 $content = str_ireplace("</ol><br />", '</ol>', $content);
3491 $content = str_ireplace("</ol>\r\n<br />", '</ol>', $content);
3492 $content = str_ireplace("</ul><br />", '</ul>', $content);
3493 $content = str_ireplace("</ul>\r\n<br />", '</ul>', $content);
3494 $content = str_ireplace("</pre>\r\n<br />", '</pre>', $content);
3495 $content = str_ireplace("</blockquote><br />", '</blockquote>', $content);
3496 $content = str_ireplace("</blockquote>\r\n<br />", '</blockquote>', $content);
3497
3498 return $content;
3499 }
3500
3501 /**
3502 * Triggers plugins.
3503 *
3504 * @since 3.0
3505 * @access public
3506 */
3507 public static function triggerPlugins( $type , $eventName , &$data ,$hasReturnValue = false )
3508 {
3509 $path = JPATH_ADMINISTRATOR . '/components/com_easydiscuss/includes/events/events.php';
3510 include_once($path);
3511
3512 EasyDiscussEvents::importPlugin($type);
3513
3514 $args = array( 'post' , &$data );
3515
3516 $returnValue = call_user_func_array( 'EasyDiscussEvents::' . $eventName , $args );
3517
3518 if ($hasReturnValue) {
3519 return trim( implode( "\n" , $returnValue ) );
3520 }
3521
3522 return;
3523 }
3524
3525 /**
3526 * Renders a module in the component
3527 *
3528 * @since 4.0
3529 * @access public
3530 * @param string
3531 * @return
3532 */
3533 public static function renderModule($position, $attributes = array(), $content = null)
3534 {
3535 jimport('joomla.application.module.helper');
3536
3537 $doc = JFactory::getDocument();
3538 $renderer = $doc->loadRenderer('module');
3539 $buffer = '';
3540 $modules = JModuleHelper::getModules($position);
3541
3542 foreach ($modules as $module) {
3543
3544 // Get the module output
3545 $output = $renderer->render($module, $attributes, $content);
3546
3547 $theme = ED::themes();
3548 $theme->set('position', $position);
3549 $theme->set('output', $output);
3550
3551 $buffer .= $theme->output('site/widgets/module');
3552 }
3553
3554 return $buffer;
3555 }
3556
3557 public static function getEditorType( $type = '' )
3558 {
3559 // Cater for #__discuss_posts column content_type
3560 $config = ED::getConfig();
3561
3562 if ($config->get('layout_editor') == 'bbcode') {
3563 return 'bbcode';
3564 } else {
3565 return 'html';
3566 }
3567 }
3568
3569 /**
3570 * Formats the content of a post
3571 *
3572 * @since 1.0
3573 * @access public
3574 * @param string
3575 * @return
3576 */
3577 public static function formatContent($post)
3578 {
3579 $config = ED::config();
3580
3581 // @ 4.0 we need to check if this post has the 'preview' or not. if yes, we just use it. if not, lets format it.
3582 if ($post->preview) {
3583
3584 // Apply word censorship on the content
3585 $content = ED::badwords()->filter($post->preview);
3586
3587 return $content;
3588 }
3589
3590 // Determine the current editor
3591 $editor = $config->get('layout_editor', 'bbcode');
3592
3593 // If the post is bbcode source and the current editor is bbcode
3594 if (($post->content_type == 'bbcode' || is_null($post->content_type)) && $editor == 'bbcode') {
3595
3596 $content = $post->content;
3597
3598 // Allow syntax highlighter even on html codes.
3599 $content = ED::parser()->replaceCodes($content);
3600
3601 $content = ED::parser()->bbcode($content , true);
3602
3603 // Since this is a bbcode content and source, we want to replace \n with <br /> tags.
3604 $content = nl2br($content);
3605 }
3606
3607 // If the admin decides to switch from bbcode to wysiwyg editor, we need to format it back
3608 if( $post->content_type == 'bbcode' && $editor != 'bbcode' )
3609 {
3610 $content = $post->content;
3611
3612 //strip this kind of tag -> &
3613 $content = strip_tags(html_entity_decode($content));
3614
3615 // Since the original content is bbcode, we don't really need to do any replacements.
3616 // Just feed it in through bbcode formatter.
3617 $content = ED::parser()->bbcode( $content );
3618 }
3619
3620 // If the admin decides to switch from wysiwyg to bbcode, we need to fix the content here.
3621 if( $post->content_type != 'bbcode' && !is_null($post->content_type) && $editor == 'bbcode' )
3622 {
3623 $content = $post->content;
3624
3625 // Switch html back to bbcode
3626 $content = ED::parser()->html2bbcode( $content );
3627
3628 // Update the quote messages
3629 $content = ED::parser()->quoteBbcode( $content );
3630 }
3631
3632 // If the content is from wysiwyg and editor is also wysiwyg, we only do specific formatting.
3633 if( $post->content_type != 'bbcode' && $editor != 'bbcode' )
3634 {
3635 $content = $post->content;
3636
3637 // Allow syntax highlighter even on html codes.
3638 $content = ED::parser()->replaceCodes( $content );
3639 }
3640
3641 // Apply word censorship on the content
3642 $content = ED::badwords()->filter($content);
3643
3644 return $content;
3645 }
3646
3647 /**
3648 * cache for post related items.
3649 *
3650 * @since 4.0
3651 * @access public
3652 * @param string
3653 * @return
3654 */
3655 public static function cache()
3656 {
3657 static $cache = null;
3658
3659 if (!$cache) {
3660 require_once(__DIR__ . '/cache/cache.php');
3661
3662 $cache = new EasyDiscussCache();
3663 }
3664
3665 return $cache;
3666 }
3667
3668 /**
3669 * cache for post related items.
3670 *
3671 * @since 4.0
3672 * @access public
3673 * @param string
3674 * @return
3675 */
3676 public static function rest()
3677 {
3678 static $rest = null;
3679
3680 if (!$rest) {
3681 require_once(__DIR__ . '/rest/rest.php');
3682
3683 $rest = new EasyDiscussRest();
3684 }
3685
3686 return $rest;
3687 }
3688
3689
3690 /**
3691 * include akisment class file
3692 *
3693 * @since 4.0
3694 * @access public
3695 * @param string
3696 * @return
3697 */
3698 public static function akismet()
3699 {
3700 if (! class_exists('Akismet')) {
3701 require_once(__DIR__ . '/akismet/akismet.php');
3702 }
3703 }
3704
3705 /**
3706 * Ensures that the token is valid
3707 *
3708 * @since 4.0
3709 * @access public
3710 * @param string
3711 * @return
3712 */
3713 public static function checkToken($method = 'post')
3714 {
3715 JRequest::checkToken($method) or die('Invalid Token');
3716 }
3717
3718 // For displaying on frontend
3719 public static function bbcodeHtmlSwitcher( $post = '', $type = '', $isEditing = false )
3720 {
3721 $config = ED::config();
3722
3723 if( $type == 'signature' || $type == 'description' ) {
3724 $temp = $post;
3725 $post = new stdClass();
3726 $post->content = $temp;
3727 $post->content_type = 'bbcode';
3728 $editor = 'bbcode';
3729 } else {
3730 $editor = $config->get( 'layout_editor' );
3731 }
3732
3733 if ($editor != 'bbcode') {
3734 $editor = 'html';
3735 }
3736
3737 if ($post->content_type == 'bbcode') {
3738 if ($editor == 'bbcode') {
3739
3740 $content = $post->content;
3741
3742 //If content_type is bbcode and editor is bbcode
3743 if (! $isEditing) {
3744 $content = ED::parser()->bbcode($content);
3745 $content = ED::parser()->removeBrTag($content);
3746 }
3747 } else {
3748 //If content_type is bbcode and editor is html
3749 // Need content raw to work
3750 $content = $post->post->content;
3751 $content = ED::parser()->bbcode($content);
3752 $content = ED::parser()->removeBrTag($content);
3753 }
3754 } else {
3755 // content_type is html
3756
3757 if ($editor == 'bbcode') {
3758
3759 $content = $post->content;
3760
3761 //If content_type is html and editor is bbcode
3762 if ($isEditing) {
3763 $content = ED::parser()->quoteBbcode($content);
3764 $content = ED::parser()->smiley2bbcode($content); // we need to parse smiley 1st before we parse htmltobbcode.
3765 $content = ED::parser()->html2bbcode($content);
3766 } else {
3767
3768 //Quote all bbcode here
3769 $content = ED::parser()->quoteBbcode($content);
3770 }
3771 } else {
3772 //If content_type is html and editor is html
3773 $content = $post->content;
3774 }
3775 }
3776
3777 // Apply censorship
3778 $content = ED::badwords()->filter($content);
3779
3780 return $content;
3781 }
3782
3783 public static function getLoginLink($returnURL = '')
3784 {
3785 if (!empty($returnURL)) {
3786 $returnURL = '&return=' . $returnURL;
3787 }
3788
3789 $link = DiscussRouter::_('index.php?option=com_users&view=login' . $returnURL);
3790
3791 return $link;
3792 }
3793
3794 public static function getPostStatusAndTypes( $posts = null)
3795 {
3796 if (empty($posts)) {
3797 return;
3798 }
3799
3800 foreach ($posts as $post) {
3801 $user = ED::user($post->getOwner()->id);
3802
3803 $post->badges = $user->getBadges();
3804
3805 // Translate post status from integer to string
3806 switch($post->post_status) {
3807 case '0':
3808 $post->post_status_class = '';
3809 $post->post_status = '';
3810 break;
3811 case '1':
3812 $post->post_status_class = '-on-hold';
3813 $post->post_status = JText::_( 'COM_EASYDISCUSS_POST_STATUS_ON_HOLD' );
3814 break;
3815 case '2':
3816 $post->post_status_class = '-accept';
3817 $post->post_status = JText::_( 'COM_EASYDISCUSS_POST_STATUS_ACCEPTED' );
3818 break;
3819 case '3':
3820 $post->post_status_class = '-working-on';
3821 $post->post_status = JText::_( 'COM_EASYDISCUSS_POST_STATUS_WORKING_ON' );
3822 break;
3823 case '4':
3824 $post->post_status_class = '-reject';
3825 $post->post_status = JText::_( 'COM_EASYDISCUSS_POST_STATUS_REJECT' );
3826 break;
3827 default:
3828 $post->post_status_class = '';
3829 $post->post_status = '';
3830 break;
3831 }
3832
3833 $alias = $post->post_type;
3834 $modelPostTypes = ED::model('Posttypes');
3835
3836 // Get each post's post status title
3837 $title = $modelPostTypes->getTitle($alias);
3838 $post->post_type = $title;
3839
3840 // Get each post's post status suffix
3841 $suffix = $modelPostTypes->getSuffix($alias);
3842 $post->suffix = $suffix;
3843 }
3844
3845 return $posts;
3846 }
3847
3848 /**
3849 * Determines if the user falls under the moderation threshold
3850 *
3851 * @since 4.0
3852 * @access public
3853 * @param string
3854 * @return
3855 */
3856 public static function isModerateThreshold($userId = null)
3857 {
3858 $user = ED::user($userId);
3859
3860 return $user->moderateUsersPost();
3861 }
3862
3863 /**
3864 * Backwards compatibility purpose
3865 *
3866 * @since 4.0
3867 * @access public
3868 * @param string
3869 * @return
3870 */
3871 public static function __callStatic($method, $args)
3872 {
3873 // If the called method exists in the legacy, we should just use it
3874 if (method_exists('EDLegacy', $method)) {
3875 return call_user_func_array(array('EDLegacy', $method), $args);
3876 }
3877
3878 // Here, we are under the assumption, the library exists
3879 $file = dirname(__FILE__) . '/' . strtolower($method) . '/' . strtolower($method) . '.php';
3880
3881 require_once($file);
3882
3883 $class = 'EasyDiscuss' . ucfirst($method);
3884
3885 if (count($args) == 1) {
3886 $args = $args[0];
3887 }
3888
3889 if (!$args) {
3890 $args = null;
3891 }
3892
3893 $obj = new $class($args);
3894
3895 return $obj;
3896 }
3897
3898 /**
3899 * Gets the current timezone of the site
3900 *
3901 * @since 4.0
3902 * @access public
3903 * @param string
3904 * @return
3905 */
3906 public static function getTimeZone()
3907 {
3908 // Get server's timezone
3909 $user = JFactory::getUser();
3910 $jconfig = ED::jconfig();
3911 $timezone = $jconfig->get('offset');
3912
3913 // If user is a member, get their timezone
3914 if ($user->id) {
3915 $timezone = $user->getParam('timezone', $timezone);
3916 }
3917
3918 return $timezone;
3919 }
3920
3921 /**
3922 * Gets the current timezone of the site
3923 *
3924 * @since 4.0
3925 * @access public
3926 * @param string
3927 * @return
3928 */
3929 public static function getTimeZoneOffset()
3930 {
3931 $date = ED::date();
3932
3933 $timezone = ED::getTimeZone();
3934 $timezone = new DateTimeZone($timezone);
3935
3936 $date->setTimezone($timezone);
3937
3938 $offset = $date->getOffsetFromGmt(true);
3939
3940 return $offset;
3941 }
3942
3943
3944 /**
3945 * Renders the DiscussProfile table
3946 *
3947 * @since 4.0
3948 * @access public
3949 * @param string
3950 * @return
3951 */
3952 public static function profile($id = null)
3953 {
3954 $user = ED::user($id);
3955 return $user;
3956 }
3957
3958 public static function validateUserType($usertype)
3959 {
3960 $config = ED::config();
3961 $acl = ED::acl();
3962
3963 switch($usertype)
3964 {
3965 case 'guest':
3966 $enable = $acl->allowed('add_reply', 0);
3967 break;
3968 case 'twitter':
3969 $enable = $config->get('integration_twitter_enable');
3970 break;
3971 case 'facebook':
3972 $enable = $config->get('integration_facebook_enable1');
3973 break;
3974 case 'linkedin':
3975 $enable = $config->get('integration_linkedin_enable1');
3976 break;
3977 default:
3978 $enable = false;
3979 }
3980
3981 return $enable;
3982 }
3983
3984 /**
3985 * Retrieves the default avatar
3986 *
3987 * @since 4.0
3988 * @access public
3989 * @param string
3990 * @return
3991 */
3992 public static function getDefaultAvatar()
3993 {
3994 $uri = rtrim(JURI::root(), '/');
3995 $file = '/media/com_easydiscuss/images/default_avatar.png';
3996
3997 // @TODO: Allow overrides
3998
3999 $uri = $uri . $file;
4000
4001 return $uri;
4002 }
4003
4004 public static function getThemeObject($name)
4005 {
4006 jimport('joomla.filesystem.file');
4007 jimport('joomla.filesystem.folder');
4008
4009 $file = DISCUSS_THEMES . '/' . $name . '/config.xml';
4010 $exists = JFile::exists($file);
4011
4012 if (!$exists) {
4013 return false;
4014 }
4015
4016 $parser = JFactory::getXML($file);
4017
4018 $obj = new stdClass();
4019 $obj->element = $name;
4020 $obj->name = $name;
4021 $obj->path = $file;
4022 $obj->writable = is_writable($file);
4023 $obj->created = JText::_('Unknown');
4024 $obj->updated = JText::_('Unknown');
4025 $obj->author = JText::_('Unknown');
4026 $obj->version = JText::_('Unknown');
4027 $obj->desc = JText::_('Unknown');
4028
4029 if (ED::isJoomla30()) {
4030
4031 $childrens = $parser->children();
4032
4033 foreach ($childrens as $key => $value) {
4034 if ($key == 'description') {
4035 $key = 'desc';
4036 }
4037
4038 $obj->$key = (string) $value;
4039 }
4040
4041 $obj->path = $file;
4042 } else {
4043
4044 $contents = JFile::read($file);
4045
4046 $parser = JFactory::getXMLParser('Simple');
4047 $parser->loadString($contents);
4048
4049 $created = $parser->document->getElementByPath('created');
4050 if ($created) {
4051 $obj->created = $created->data();
4052 }
4053
4054 $updated = $parser->document->getElementByPath('updated');
4055 if ($updated) {
4056 $obj->updated = $updated->data();
4057 }
4058
4059 $author = $parser->document->getElementByPath('author');
4060 if ($author) {
4061 $obj->author = $author->data();
4062 }
4063
4064 $version = $parser->document->getElementByPath('version');
4065 if ($version) {
4066 $obj->version = $version->data();
4067 }
4068
4069 $description = $parser->document->getElementByPath('description');
4070 if ($description)
4071 {
4072 $obj->desc = $description->data();
4073 }
4074
4075 $obj->path = $file;
4076 }
4077
4078 return $obj;
4079 }
4080
4081 /**
4082 * Parses a csv file to array of data
4083 *
4084 * @since 4.0
4085 * @param string Filename to parse
4086 * @return Array Arrays of the data
4087 */
4088 public static function parseCSV($file, $firstRowName = true, $firstColumnKey = true)
4089 {
4090 if (!JFile::exists($file)) {
4091 return array();
4092 }
4093
4094 $handle = fopen($file, 'r');
4095
4096 $line = 0;
4097
4098 $columns = array();
4099
4100 $data = array();
4101
4102 while (($row = fgetcsv($handle)) !== false) {
4103
4104 if ($firstRowName && $line === 0) {
4105 $columns = $row;
4106 } else {
4107 $tmp = array();
4108
4109 if ($firstRowName) {
4110 foreach ($row as $i => $v) {
4111 $tmp[$columns[$i]] = $v;
4112 }
4113 } else {
4114 $tmp = $row;
4115 }
4116
4117 if ($firstColumnKey) {
4118 if ($firstRowName) {
4119 $data[$tmp[$columns[0]]] = $tmp;
4120 } else {
4121 $data[$tmp[0]] = $tmp;
4122 }
4123 } else {
4124 $data[] = $tmp;
4125 }
4126 }
4127
4128 $line++;
4129 }
4130
4131 fclose($handle);
4132
4133 return $data;
4134 }
4135
4136 /**
4137 * Includes a file given a particular namespace in POSIX format.
4138 *
4139 * @since 4.0
4140 * @access public
4141 * @param string $file Eg: admin:/tables/table will include /administrator/components/com_easydiscuss/tables/table.php
4142 * @return boolean True on success false otherwise
4143 */
4144 public static function import( $namespace )
4145 {
4146 static $locations = array();
4147
4148 if( !isset( $locations[ $namespace ] ) )
4149 {
4150 // Explode the parts to know exactly what to lookup for
4151 $parts = explode( ':' , $namespace );
4152
4153 // Non POSIX standard.
4154 if( count( $parts ) <= 1 )
4155 {
4156 return false;
4157 }
4158
4159 $base = $parts[ 0 ];
4160
4161 switch( $base )
4162 {
4163 case 'admin':
4164 $basePath = DISCUSS_ADMIN_ROOT;
4165 break;
4166 case 'site':
4167 default:
4168 $basePath = DISCUSS_ROOT;
4169 break;
4170 }
4171
4172 // Replace / with proper directory structure.
4173 $path = str_ireplace( '/' , DIRECTORY_SEPARATOR , $parts[ 1 ] );
4174
4175 // Get the absolute path now.
4176 $path = rtrim($basePath, '/') . '/' . $path . '.php';
4177
4178 // Include the file now.
4179 include_once( $path );
4180
4181 $locations[ $namespace ] = true;
4182 }
4183
4184 return true;
4185 }
4186
4187 /**
4188 * Generates the query string for language selection.
4189 *
4190 * @since 4.0
4191 * @access public
4192 * @param string
4193 * @return
4194 */
4195 public static function getLanguageQuery($column = 'language')
4196 {
4197 $language = JFactory::getLanguage();
4198 $tag = $language->getTag();
4199 $query = '';
4200
4201 $column = (!$column)? 'language' : $column;
4202
4203 if (!empty($tag) && $tag != '*') {
4204 $db = ED::db();
4205 $query = ' (' . $db->qn($column) . '=' . $db->Quote($tag) . ' OR ' . $db->qn($column) . '=' . $db->Quote('') . ' OR ' . $db->qn($column) . '=' . $db->Quote('*') . ')';
4206 }
4207
4208 return $query;
4209 }
4210
4211 /**
4212 * Sets some callback data into the current session
4213 *
4214 * @since 1.0
4215 * @access public
4216 * @param string
4217 * @return
4218 */
4219 public static function setCallback($data)
4220 {
4221 $session = JFactory::getSession();
4222
4223 // Serialize the callback data.
4224 $data = serialize( $data );
4225
4226 // Store the profile type id into the session.
4227 $session->set('easydiscuss.callback', $data, 'com_easydiscuss');
4228 }
4229
4230 /**
4231 * Retrieves stored callback data.
4232 *
4233 * @since 1.0
4234 * @access public
4235 * @param string
4236 * @return
4237 */
4238 public static function getCallback()
4239 {
4240 $session = JFactory::getSession();
4241 $data = $session->get('easydiscuss.callback', '', 'com_easydiscuss');
4242
4243 $data = unserialize( $data );
4244
4245 // Clear off the session once it's been picked up.
4246 $session->clear('easydiscuss.callback', 'com_easydiscuss');
4247
4248 return $data;
4249 }
4250
4251 /**
4252 * Retrieves external conversation link
4253 *
4254 * @since 4.0
4255 * @access public
4256 * @param string
4257 * @return
4258 */
4259 public static function getConversationsRoute()
4260 {
4261 $config = ED::config();
4262
4263 if (ED::easysocial()->exists() && $config->get('integration_easysocial_messaging')) {
4264 $link = ED::easysocial()->getConversationsRoute();
4265 }
4266
4267 if (ED::jomsocial()->exists() && $config->get('integration_jomsocial_messaging')) {
4268 $link = ED::jomsocial()->getConversationsRoute();
4269 }
4270
4271 return $link;
4272 }
4273}
4274
4275// Backwards compatibility
4276class DiscussHelper extends ED {}