<?php
/**
* @copyright (C) 2013 iJoomla, Inc. - All rights reserved.
* @license GNU General Public License, version 2 (http://www.gnu.org/licenses/gpl-2.0.html)
* @author iJoomla.com <webmaster@ijoomla.com>
* @url https://www.jomsocial.com/license-agreement
* The PHP code portions are distributed under the GPL license. If not otherwise stated, all images, manuals, cascading style sheets, and included JavaScript *are NOT GPL, and are released under the IJOOMLA Proprietary Use License v1.0
* More info at https://www.jomsocial.com/license-agreement
*/

use Joomla\CMS\Component\Router\RouterBase;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Table\Table;

defined('_JEXEC') or die('Restricted access');

include_once JPATH_BASE.'/components/com_community/libraries/core.php';

class CommunityRouter extends RouterBase
{
	function build(&$query)
	{
		$app      = Factory::getApplication();
		$segments = array();
		$config   = CFactory::getConfig();
		$alias    = '';

		// Profile based,
		if (array_key_exists('userid', $query))
		{
			$user       = CFactory::getUser($query['userid']);

			// Since 1.8.x we will generate URLs based on the vanity url.
			$alias = $user->getAlias();
			$alias = CString::str_ireplace(':', '-', $alias);
			$segments[] = $alias;

			unset($query['userid']);
		}

		// @rule: For those my-xxx tasks, we need
		// to force the userid to be rewritten in the URL to maintain compatibility with
		// older URLs.
		if (isset($query['task']) && empty($alias))
		{
			$userTasks = array('myvideos', 'myphotos', 'myevents', 'mygroups', 'mypages');

			if (in_array($query['task'], $userTasks))
			{
				$user       = CFactory::getUser();
				$segments[] = $user->getAlias();
			}
		}

		if (isset($query['view']))
		{
			if (empty($query['Itemid']))
			{
				$segments[] = $query['view'];
			}
			else
			{
				$menu     = $app->getMenu();
				$menuItem = $menu->getItem( $query['Itemid'] );

				if ( ! isset($menuItem->query['view']) || $menuItem->query['view'] != $query['view'])
				{
					$segments[] = $query['view'];
				}
			}

			unset($query['view']);
		}

		if (isset($query['task']))
		{
			switch ($query['task'])
			{
				case 'callback':
					$segments[] = 'callback';
					if (isset($query['app']) && $query['app']) {
						$segments[] = $query['app'];
						unset($query['app']);

						if (isset($query['login']) && $query['login']) {
							$segments[] = 'login';
							unset($query['login']);
						}
					}
					break;

				case 'viewpage':
					$db         = Factory::getDBO();
					$pageid    =  $query['pageid'];
					$pageModel =  CFactory::getModel('pages');
					$page      = Table::getInstance('Page', 'CTable');
					$page->load($pageid);

					$segments[] = $query['task'];

					if ($page->alias) {
						$pageName = $page->alias;
					} else {
						$pageName = $page->name;
					}

					if (Factory::getConfig()->get('unicodeslugs', 0) == 1)
					{
						$pageName = OutputFilter::stringURLUnicodeSlug($pageName);
					}
					else
					{
						$pageName = OutputFilter::stringURLSafe($pageName);
					}

					$segments[] = $pageid . '-' . $pageName;

					unset($query['pageid']);
				break;
				case 'viewgroup':
					$db         = Factory::getDBO();
					$groupid    =  $query['groupid'];
					$groupModel =  CFactory::getModel('groups');
					$group      = Table::getInstance('Group', 'CTable');
					$group->load($groupid);

					$segments[] = $query['task'];

					if ($group->alias) {
						$groupName = $group->alias;
					} else {
						$groupName = $group->name;
					}

					//if ($jconfig->get('unicodeslugs', 0) == 1)
					if (Factory::getConfig()->get('unicodeslugs', 0) == 1)
					{
						$groupName = OutputFilter::stringURLUnicodeSlug($groupName);
					}
					else
					{
						$groupName = OutputFilter::stringURLSafe($groupName);
					}

					$segments[] = $groupid . '-' . $groupName;

					unset($query['groupid']);
				break;
				case 'viewevent':
					$id    = $query['eventid'];
					$event = Table::getInstance('Event' , 'CTable');
					$event->load($id);

					$segments[] = $query['task'];
					$name       = $event->title;

					//if ($jconfig->get('unicodeslugs', 0) == 1)
					if (Factory::getConfig()->get('unicodeslugs', 0) == 1)
					{
						$name = OutputFilter::stringURLUnicodeSlug($name);
					}
					else
					{
						$name = OutputFilter::stringURLSafe($name);
					}

					$name       = urlencode($name);
					$name       = CString::str_ireplace('++', '+', $name);
					$segments[] = $event->id . '-' . $name;

					unset($query['eventid']);
				break;
				case 'video':
					$videoModel	= CFactory::getModel('Videos');
					$videoid	= $query['videoid'];
					$video		= Table::getInstance('Video' , 'CTable');
					$video->load($videoid);

					// We need the task for video otherwise we cannot differentiate between myvideos
					// and viewing a video since myvideos also doesn't pass any tasks.
					$segments[] = $query['task'];
					$title      = trim($video->title);

					//if ($jconfig->get('unicodeslugs', 0) == 1)
					if (Factory::getConfig()->get('unicodeslugs', 0) == 1)
					{
						$title = OutputFilter::stringURLUnicodeSlug($title);
					}
					else
					{
						$title = OutputFilter::stringURLSafe($title);
					}

					$segments[]	= $video->id.'-'.$title;
					unset($query['videoid']);
				break;
				case 'viewdiscussion':
					$db               = Factory::getDBO();
					$topicId          =  $query['topicid'];
					$discussionsModel =  CFactory::getModel('discussions');
					$discussions      = Table::getInstance('Discussion', 'CTable');
					$discussions->load($topicId);

					$segments[]     = $query['task'];
					$discussionName = $discussions->title;

					//if ($jconfig->get('unicodeslugs', 0) == 1)
					if ($app->get('unicodeslugs', 0) == 1)
					{
						$discussionName = OutputFilter::stringURLUnicodeSlug($discussionName);
					}
					else
					{
						$discussionName = OutputFilter::stringURLSafe($discussionName);
					}

					$segments[] = $topicId.'-'.$discussionName;

					unset($query['topicid']);
				break;
				case 'viewbulletin':
					$db             = Factory::getDBO();
					$bulletinid     =  $query['bulletinid'];
					$bulletinsModel =  CFactory::getModel('bulletins');
					$bulletins      = Table::getInstance( 'Bulletin' , 'CTable' );
					$bulletins->load($bulletinid);

					$segments[]    = $query['task'];
					$bullentinName = $bulletins->title;

					//if ($jconfig->get('unicodeslugs', 0) == 1)
					if ($app->get('unicodeslugs', 0) == 1)
					{
						$bullentinName = OutputFilter::stringURLUnicodeSlug($bullentinName);
					}
					else
					{
						$bullentinName = OutputFilter::stringURLSafe($bullentinName);
					}

					$segments[] = $bulletinid . '-' . $bullentinName;

					unset($query['bulletinid']);
				break;
				default:
					if ( ! in_array($query['task'], array('myphotos', 'mygroups', 'mypages', 'myevents', 'myvideos', 'invites')))
					{
						$segments[] = $query['task'];
					}
				break;
			}

			unset($query['task']);
		}

		return $segments;
	}

	function parse(&$segments)
	{
		include_once JPATH_BASE.'/components/com_community/libraries/core.php';

		$site 		= Factory::getApplication();
		$vars         = array();
		$menu         = $site->getMenu();
		$selectedMenu = $menu->getActive();

		// We need to grab the user id first see if the first segment is a user
		// because once CFactory::getConfig is loaded, it will automatically trigger
		// the plugins. Once triggered, the getRequestUser will only get the current user.
		$count = count($segments);

		if ( ! empty($count))
		{
			$alias  = $segments[0];
			$userid = '';

			if ( ! empty($alias))
			{
				// Check if this user exists in the alias
				$userid = $this->CommunityGetUserId($alias);

				//check for alternative alias that might exists
				if(isset($segments[2]) && !$userid && $segments[1] == 'profile' && $segments[0] == 'community'){
					// the user might exists at third slot of the segment
					$alias = $segments[2];
				}

				// Joomla converts ':' to '-' when encoding and during decoding,
				// it converts '-' to ':' back for the query string which will break things
				// if the username has '-'. So we do not have any choice apart from
				// testing both this values until Joomla tries to fix this
				if ( ! $userid && stristr($alias , ':'))
				{
					$userid = $this->CommunityGetUserId(CString::str_ireplace(':', '-', $alias));
				}

				// For users
				if ( ! $userid)
				{

					if (stristr($alias, '-'))
					{
						$user = explode('-', $alias);

						if (isset($user[0]))
						{
							$userid	= $user[0];
						}
					}

					if (stristr($alias, ':'))
					{
						$user = explode('-', CString::str_ireplace(':', '-', $alias));

						if ( isset($user[0]))
						{
							$userid	= $user[0];
						}
					}

					if (!$userid){
						if(isset($segments[1]) && $segments[1] == 'profile'){
							$site->enqueueMessage(Text::_('COM_COMMUNITY_USER_NOT_FOUND'), 'error');
							$site->redirect(CRoute::_('index.php?option=com_community&view=frontpage', false));
						}
					}
				}
			}

			if ($userid != 0)
			{
				array_shift($segments);
				$vars['userid'] = $userid;

				// if empty, we should display the user's profile
				if (empty($segments))
				{
					$vars['view'] = 'profile';
				}
			}
		}

		$count = count($segments);

		if ( ! isset($selectedMenu))
		{
			if ($count > 0)
			{
				// If there are no menus we try to use the segments
				$vars['view'] = $segments[0];
				unset($segments[0]);

				if ( ! empty($segments[1]))
				{
					$vars['task'] = $segments[1];
					unset($segments[1]);
				}

				if ($vars['view'] === 'oauth' && $vars['task'] === 'callback' && isset($segments[2])) {
					$vars['app'] = $segments[2];
					unset($segments[2]);

					if (isset($segments[3]) && $segments[3] === 'login') {
						$vars['login'] = 1;
						unset($segments[3]);
					}
				}

				if ( ! empty($segments[2]) && $segments[1] == 'viewgroup')
				{
					$groupTitle      = $segments[2];
					$vars['groupid'] = $this->_parseGroup( $groupTitle );

					unset($segments[2]);
				}

				if ( ! empty($segments[2]) && $segments[1] == 'viewpage')
				{
					$pageTitle      = $segments[2];
					$vars['pageid'] = $this->_parsePage( $pageTitle );

					unset($segments[2]);
				}
			}

			return $vars;
		}

		if ($selectedMenu->query['view'] == 'frontpage')
		{
			// We know this is a frontpage view in the menu, try to get the
			// view from the segments instead.
			if ($count > 0)
			{
				$vars['view'] = $segments[0];
				unset($segments[0]);

				if ( ! empty($segments[1]))
				{
					$vars['task'] = $segments[1];
					unset($segments[1]);
				}
			}
		}
		else
		{
			$vars['view'] = $selectedMenu->query['view'];

			if ($count > 0)
			{
				$vars['task'] = $segments[0];
				unset($segments[0]);
			}
		}

		// In case of video view, the 'task' (video) has been removed during
		// BuildRoute. We need to detect if the segment[0] is actually a
		// permalink to the actual video, and add the proper task
		if ($segments && $vars['view'] == 'videos' && (isset($vars['task']) && $vars['task'] != 'myvideos'))
		{
			$pattern    = "'^[0-9]+'s";
			$keys = array_keys($segments);
			$videoTitle = $segments[$keys[0]];

			preg_match($pattern, $videoTitle, $matches);

			if ($matches)
			{
				$vars['task'] = 'video';
			}
		}

		if (isset($vars['userid']) && ! isset($vars['task']))
		{
			switch ($vars['view'])
			{
				case 'photos' :
					$vars['task'] = 'myphotos';
					break;
				case 'groups' :
					$vars['task'] = 'mygroups';
					break;
				case 'pages' :
					$vars['task'] = 'mypages';
					break;
				case 'events' :
					$vars['task'] = 'myevents';
					break;
				case 'videos' :
					$vars['task'] = 'myvideos';
					break;
			}
		}

		// In case users try to access http://site.com/community/my-xxx.html directly, it should also work
		if (isset($vars['task']) && $vars['task'] == 'my:pages')
		{
			$vars['view'] = 'pages';
			$vars['task'] = 'mypages';
		}

		if (isset($vars['task']) && $vars['task'] == 'my:groups')
		{
			$vars['view'] = 'groups';
			$vars['task'] = 'mygroups';
		}

		if (isset($vars['task']) && $vars['task'] == 'my:videos')
		{
			$vars['view'] = 'videos';
			$vars['task'] = 'myvideos';
		}

		if (isset($vars['view']) && $vars['view'] == 'my:photos')
		{
			$vars['view'] = 'photos';
			$vars['task'] = 'myphotos';
		}

		if (isset($vars['view']) && $vars['view'] == 'my:events')
		{
			$vars['view'] = 'events';
			$vars['task'] = 'myevents';
		}

		// If the task is video then, query the last segment to grab the video id
		if (isset($vars['task']) && $vars['task'] == 'video')
		{
			$videoTitle      = array_shift($segments);
			$titles          = explode('-', $videoTitle);
			$vars['videoid'] = $titles[0];
		}

		// If the task is viewgroup then, query the last segment to grab the group id
		if (isset($vars['task']) && $vars['task'] == 'viewgroup')
		{
			$groupTitle      = array_shift($segments);
			$vars['groupid'] = $this->_parseGroup($groupTitle);
		}

		if (isset($vars['task']) && $vars['task'] == 'viewpage')
		{
			$pageTitle      = array_shift($segments);
			$vars['pageid'] = $this->_parsePage($pageTitle);
		}

		// If the task is viewevent then, query the last segment to grab the eventid
		if (isset($vars['task']) && $vars['task'] == 'viewevent')
		{
			$title  = array_shift($segments);
			$titles = explode('-' , $title);

			// @rule: Joomla replaces - with : for the first occurence. So we need to replace the first : to -
			if (count($titles) == 1)
			{
				$titles	= explode('-', CString::str_ireplace(':' , '-', $title));
			}

			$vars['eventid'] = $titles[ 0 ];
		}

		// If the task is viewdiscussion then, query the last segment to grab the topic id
		if (isset($vars['task']) && $vars['task'] == 'viewdiscussion')
		{
			$discussionTitle = array_shift($segments);
			$titles          = explode('-', $discussionTitle);

			// @rule: Joomla replaces - with : for the first occurence. So we need to replace the first : to -
			if (count($titles) == 1)
			{
				$titles	= explode('-', CString::str_ireplace(':' ,'-' , $discussionTitle));
			}

			$vars['topicid'] = $titles[0];
		}

		// If the task is viewgroup then, query the last segment to grab the group id
		if (isset($vars['task']) && $vars['task'] == 'viewbulletin')
		{
			$bulletinTitle = array_shift($segments);
			$titles        = explode('-', $bulletinTitle);

			// @rule: Joomla replaces - with : for the first occurence. So we need to replace the first : to -
			if (count($titles) == 1)
			{
				$titles	= explode('-', CString::str_ireplace(':', '-', $bulletinTitle));
			}

			$vars['bulletinid'] = $titles[0];
		}

		return $vars;
	}

	function _parseGroup($title)
	{
		$titles  = explode('-', $title);
		$groupId = $titles[0];

		return $groupId;
	}

	function _parsePage($title)
	{
		$titles  = explode('-', $title);
		$pageId = $titles[0];

		return $pageId;
	}

	function CommunityGetUserId($alias)
	{
		$db = Factory::getDBO();
		$query = 'SELECT ' . $db->quoteName('userid').' FROM '.$db->quoteName('#__community_users')
						.' WHERE '.$db->quoteName('alias').'='.$db->Quote( $alias );
		$db->setQuery($query);
		$id = $db->loadResult();

		// The alias not found, could be caused by Joomla rewriting - into :
		// Replace the first : into - and search again
		if (empty($id))
		{
			$pattern     = '/([0-9]*)(:)/i';
			$replacement = '$1-';

			// Replace only the first occurance of : into -
			$alias = preg_replace($pattern, $replacement, $alias, 1);

			$query = 'SELECT '.$db->quoteName('userid')
						.' FROM '.$db->quoteName('#__community_users').' WHERE '.$db->quoteName('alias').'='.$db->Quote( $alias );
			$db->setQuery($query);
			$id = $db->loadResult();
		}

		return $id;
	}
}
