<?php
/**
 * @version        3.5.0
 * @package        Joomla
 * @subpackage     Helpdesk Pro
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2013 - 2019 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

namespace OSSolution\HelpdeskPro\Site\Helper;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Mail\MailHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\User\UserHelper;
use OSL\Utils\Database as DatabaseUtils;
use OSSolution\HelpdeskPro\Site\Helper\Route as RouteHelper;

defined('_JEXEC') or die;

class Helper
{
	/**
	 * Get current installed version of Helpdesk Pro
	 *
	 * @return string
	 */
	public static function getInstalledVersion()
	{
		return '4.1.0';
	}

	/**
	 * Helper method to check if the extension is running on Joomla 4
	 *
	 * @return bool
	 */
	public static function isJoomla4()
	{
		return version_compare(JVERSION, '4.0.0-dev', 'ge');
	}

	/**
	 * Get configuration data and store in config object
	 *
	 * @return \OSL\Config\Config
	 */
	public static function getConfig()
	{
		static $config;

		if (!$config)
		{
			$db    = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select('*')->from('#__helpdeskpro_configs');
			$db->setQuery($query);
			$rows = $db->loadObjectList();
			$data = [];

			foreach ($rows as $row)
			{
				$data[$row->config_key] = $row->config_value;
			}

			$config = new \OSL\Config\Config($data);
		}

		return $config;
	}

	/**
	 * Get the email messages used for sending emails
	 *
	 * @return \OSL\Config\Config
	 */
	public static function getEmailMessages()
	{
		static $message;

		if (!$message)
		{
			$db    = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select('*')->from('#__helpdeskpro_emails');
			$db->setQuery($query);
			$rows = $db->loadObjectList();
			$data = [];

			foreach ($rows as $row)
			{
				$data[$row->email_key] = $row->email_message;
			}

			$message = new \OSL\Config\Config($data);
		}

		return $message;
	}

	/**
	 * Get all custom fields assigned to certain category
	 *
	 * @param   int    $categoryId
	 * @param   array  $filters
	 *
	 * @return mixed
	 */
	public static function getFields($categoryId, $filters = [])
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('id, name, fieldtype, title')
			->from('#__helpdeskpro_fields')
			->where('(category_id = -1 OR id IN (SELECT field_id FROM #__helpdeskpro_field_categories WHERE category_id=' . (int) $categoryId . '))')
			->where('published = 1');

		foreach ($filters as $filter)
		{
			$query->where($filter);
		}

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Get all custom fields
	 *
	 * @return array
	 */
	public static function getAllFields()
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('*, extra AS extra_attributes, 0 AS max_length, "" AS place_holder')
			->from('#__helpdeskpro_fields')
			->where('published = 1')
			->order('ordering');

		if ($fieldSuffix = Helper::getFieldSuffix())
		{
			\OSL\Utils\Database::getMultilingualFields($query, ['title', 'description', 'values', 'default_values'], $fieldSuffix);
		}

		$db->setQuery($query);

		return $db->loadObjectList();
	}

	/**
	 * Get the association array contains the relationship between field and categories
	 *
	 * @return array
	 */
	public static function getFieldCategoryRelation()
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('id')
			->from('#__helpdeskpro_fields')
			->where('published = 1')
			->where('category_id = -1');
		$db->setQuery($query);

		$relation[0] = $db->loadColumn();

		$query->clear()
			->select('*')
			->from('#__helpdeskpro_field_categories');
		$db->setQuery($query);
		$fieldCategories = $db->loadObjectList();

		foreach ($fieldCategories as $fieldCategory)
		{
			$relation[$fieldCategory->category_id][] = $fieldCategory->field_id;
		}


		return $relation;
	}

	/**
	 * Get specify config value
	 *
	 * @param   string  $key
	 *
	 * @return string
	 */
	public static function getConfigValue($key)
	{
		$config = static::getConfig();

		return $config->get($key);
	}

	/**
	 * Get Itemid of Helpdesk Pro componnent
	 *
	 * @return int
	 */
	public static function getItemid()
	{
		$db    = Factory::getDbo();
		$user  = Factory::getUser();
		$query = $db->getQuery(true);
		$query->select('id')
			->from('#__menu AS a')
			->where('a.link LIKE "%index.php?option=com_helpdeskpro&view=tickets%"')
			->where('a.published=1')
			->where('a.access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');

		if (Multilanguage::isEnabled())
		{
			$query->where('a.language IN (' . $db->quote(Factory::getLanguage()->getTag()) . ',' . $db->Quote('*') . ')');
		}

		$query->order('a.access');
		$db->setQuery($query);
		$itemId = $db->loadResult();

		if (!$itemId)
		{
			$Itemid = Factory::getApplication()->input->getInt('Itemid');

			if ($Itemid == 1)
			{
				$itemId = 999999;
			}
			else
			{
				$itemId = $Itemid;
			}
		}

		return $itemId;
	}

	/**
	 * Get field suffix used in sql query
	 *
	 * @param   string  $activeLanguage
	 *
	 * @return string
	 */
	public static function getFieldSuffix($activeLanguage = null)
	{
		$prefix = '';

		if (Multilanguage::isEnabled())
		{
			if (!$activeLanguage)
			{
				$activeLanguage = Factory::getLanguage()->getTag();
			}

			if ($activeLanguage != self::getDefaultLanguage())
			{
				$db    = Factory::getDbo();
				$query = $db->getQuery(true);
				$query->select('`sef`')
					->from('#__languages')
					->where('lang_code = ' . $db->quote($activeLanguage))
					->where('published = 1');
				$db->setQuery($query);
				$sef = $db->loadResult();

				if ($sef)
				{
					$prefix = '_' . $sef;
				}
			}
		}

		return $prefix;
	}

	/**
	 * load editable
	 */
	public static function loadEditable($loadJs = true)
	{
		$document = Factory::getDocument();
		$rootUri  = Uri::root(true);
		$config   = static::getConfig();

		if ($config->twitter_bootstrap_version === '4' && Factory::getApplication()->isClient('site'))
		{
			return;
		}

		if ($config->twitter_bootstrap_version == '3' && Factory::getApplication()->isClient('site'))
		{
			$editable = 'bs3editable';
		}
		else
		{
			$editable = 'editable';
		}

		$document->addStyleSheet($rootUri . '/media/com_helpdeskpro/assets/js/' . $editable . '/css/bootstrap-editable.css');

		if ($loadJs)
		{
			$document->addScript($rootUri . '/media/com_helpdeskpro/assets/js/' . $editable . '/js/bootstrap-editable.min.js');
		}
	}

	/**
	 * Load highlighter script so that the code will be highlighted
	 */
	public static function loadHighlighter()
	{
		$config             = self::getConfig();
		$supportedLanguages = explode(',', $config->programming_languages);
		$syntaxPath         = Uri::root(true) . '/media/com_helpdeskpro/assets/js/syntaxhighlighter3/';
		$document           = Factory::getDocument();
		$document->addScript($syntaxPath . 'scripts/shCore.js');
		$languages = [
			'AS3',
			'Bash',
			'Cpp',
			'CSharp',
			'Css',
			'Delphi',
			'Diff',
			'Groovy',
			'Java',
			'JavaFX',
			'JScript',
			'Perl',
			'Php',
			'Plain',
			'PowerShell',
			'Python',
			'Ruby',
			'Scala',
			'Sql',
			'Vb',
			'Xml'];

		foreach ($languages as $language)
		{
			if (in_array($language, $supportedLanguages))
			{
				$document->addScript($syntaxPath . 'scripts/shBrush' . $language . '.js');
			}
		}

		$theme = 'Default';
		$document->addStyleSheet($syntaxPath . 'styles/shCore' . $theme . '.css');
		$document->addStyleSheet($syntaxPath . 'styles/shTheme' . $theme . '.css');
		$document->addScriptDeclaration('
			  SyntaxHighlighter.all();
		 ');
	}

	/**
	 *
	 *
	 * @return string
	 */
	public static function validateEngine()
	{
		$dateNow    = HTMLHelper::_('date', Factory::getDate(), 'Y/m/d');
		$validClass = [
			"",
			"validate[custom[integer]]",
			"validate[custom[number]]",
			"validate[custom[email]]",
			"validate[custom[url]]",
			"validate[custom[phone]]",
			"validate[custom[date],past[$dateNow]]",
			"validate[custom[ipv4]]",
			"validate[minSize[6]]",
			"validate[maxSize[12]]",
			"validate[custom[integer],min[-5]]",
			"validate[custom[integer],max[50]]"];

		return json_encode($validClass);
	}

	/**
	 *
	 * Get role of the given user
	 *
	 * @param $userId
	 *
	 * @return mixed
	 */
	public static function getUserRole($userId = 0)
	{
		static $roles = [];

		if (!$userId)
		{
			$userId = Factory::getUser()->id;
		}

		if (!isset($roles[$userId]))
		{
			$role = 'user';

			if ($userId)
			{
				$user = Factory::getUser($userId);

				if ($user->authorise('core.admin', 'com_helpdeskpro'))
				{
					$role = 'admin';
				}
				else
				{
					$manageCategoryIds = Helper::getTicketCategoryIds($user->username);

					if (count($manageCategoryIds) >= 1 && $manageCategoryIds[0] != 0)
					{
						$role = 'manager';
					}
					else
					{
						$config = self::getConfig();

						if ($config->staff_group_id)
						{
							$staffs = Database::getAllStaffs($config->staff_group_id);

							foreach ($staffs as $staff)
							{
								if ($staff->id == $userId)
								{
									$role = 'staff';
									break;
								}
							}
						}
					}
				}
			}

			$roles[$userId] = $role;
		}

		return $roles[$userId];
	}

	/**
	 * Get list of current online users
	 *
	 * @return array
	 */
	public static function getOnlineUsers()
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('DISTINCT u.id');
		$query->from('#__session AS s');
		$query->innerJoin('#__users AS u ON s.userid = u.id');
		$query->where('s.guest = 0');
		$db->setQuery($query);

		return $db->loadColumn();
	}

	/**
	 * Load language from main component
	 *
	 */
	public static function loadLanguage()
	{
		static $loaded;

		if (!$loaded)
		{
			$lang = Factory::getLanguage();
			$tag  = $lang->getTag();

			if (!$tag)
			{
				$tag = 'en-GB';
			}

			$lang->load('com_helpdeskpro', JPATH_ROOT, $tag);
			$loaded = true;
		}
	}

	/**
	 * Display copy right information
	 *
	 */
	public static function displayCopyRight()
	{
		echo '<div class="copyright clearfix row-fluid" style="text-align:center;margin-top: 5px;"><a href="http://joomdonation.com/components/helpdesk-pro.html" target="_blank"><strong>Helpdesk Pro</strong></a> version ' . self::getInstalledVersion() . ', Copyright (C) 2012 - ' . date('Y') . ' <a href="http://joomdonation.com" target="_blank"><strong>Ossolution Team</strong></a></div>';
	}

	/**
	 * Get ticket categories managed by the given user
	 *
	 * @param   string  $username
	 *
	 * @return array
	 */
	public static function getTicketCategoryIds($username)
	{
		static $categories = [];

		if (!isset($categories[$username]))
		{
			$db    = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select('id')
				->from('#__helpdeskpro_categories')
				->where("managers='$username' OR managers LIKE '$username,%' OR managers LIKE '%,$username,%' OR managers LIKE '%,$username'");
			$db->setQuery($query);

			$categoryIds = $db->loadColumn();

			if (!count($categoryIds))
			{
				$categoryIds = [0];
			}

			$categories[$username] = $categoryIds;
		}

		return $categories[$username];
	}

	/**
	 * Method to check to see whether the user can edit the comment
	 *
	 * @param   \JUser  $user
	 * @param   int     $id
	 *
	 * @return bool
	 */
	public static function canUpdateComment($user, $id)
	{
		if (static::isJoomla4())
		{
			return false;
		}

		// User has edit permission in helpdesk pro will be able to edit the comment
		if ($user->authorise('core.edit', 'com_helpdeskpro'))
		{
			return true;
		}

		// Owner of the ticket can edit the comment
		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('user_id')
			->from('#__helpdeskpro_messages')
			->where('id = ' . $id);
		$db->setQuery($query);
		$message = $db->loadObject();

		if ($message && $user->id && ($message->user_id == $user->id) && $user->authorise('core.editown', 'com_helpdeskpro'))
		{
			return true;
		}

		// Otherwise, he could not edit the comment
		return false;
	}

	/**
	 * Helper methd to check to see whether the user can edit the comment
	 *
	 * @param   \JUser  $user
	 * @param           $id
	 *
	 * @return bool
	 */
	public static function canDeleteComment($user, $id)
	{
		// User has edit permission in helpdesk pro will be able to edit the comment
		if ($user->authorise('core.delete', 'com_helpdeskpro'))
		{
			return true;
		}

		// Owner of the ticket can edit the comment
		$db    = Factory::getDbo();
		$query = $db->getQuery(true);
		$query->select('user_id')
			->from('#__helpdeskpro_messages')
			->where('id = ' . $id);
		$db->setQuery($query);
		$message = $db->loadObject();

		if ($message && $user->id && ($message->user_id == $user->id))
		{
			return true;
		}

		// Otherwise, he could not edit the comment

		return false;
	}

	/**
	 * Check ticket access
	 *
	 * @param   \Ossolution\HelpdeskPro\Admin\Table\Ticket  $item
	 *
	 * @return bool
	 */
	public static function checkTicketAccess($item)
	{
		$user   = Factory::getUser();
		$config = Helper::getConfig();

		if (!$item->id)
		{
			return false;
		}

		if ($item->is_ticket_code && $config->allow_public_user_submit_ticket)
		{
			return true;
		}

		if (!$user->id)
		{
			return false;
		}

		if ($user->id == $item->user_id || $user->email == $item->email)
		{
			return true;
		}

		if ($user->id == $item->staff_id)
		{
			return true;
		}

		if ($user->authorise('core.admin', 'com_helpdeskpro'))
		{
			return true;
		}

		$managedCategoryIds = Helper::getTicketCategoryIds($user->get('username'));

		if (in_array($item->category_id, $managedCategoryIds))
		{
			return true;
		}

		return false;
	}

	/**
	 * Get CB avatar of the given user to display on the ticket
	 *
	 * @param   int  $userId
	 *
	 * @return string relative path to the avatar
	 */
	public static function getCBAvatar($userId)
	{
		static $avatars;

		if (!isset($avatars[$userId]))
		{
			$db    = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select('avatar')
				->from('#__comprofiler')
				->where('user_id=' . $userId . ' AND avatarapproved=1');
			$db->setQuery($query);
			$avatar = $db->loadResult();
			if (!$avatar)
				$avatar = '';
			$avatars[$userId] = $avatar;
		}

		return $avatars[$userId];
	}

	/**
	 * This function is used to check to see whether we need to update the database to support multilingual or not
	 *
	 * @return boolean
	 */
	public static function isSyncronized()
	{
		$db             = Factory::getDbo();
		$fields         = $db->getTableColumns('#__helpdeskpro_categories');
		$fields         = array_keys($fields);
		$extraLanguages = self::getLanguages(self::getDefaultLanguage());

		if (count($extraLanguages))
		{
			foreach ($extraLanguages as $extraLanguage)
			{
				$prefix = $extraLanguage->sef;

				if (!in_array('title_' . $prefix, $fields))
				{
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Syncronize Helpdesk Pro database to support multilingual
	 */
	public static function setupMultilingual()
	{
		$db        = Factory::getDbo();
		$languages = self::getLanguages();

		if (count($languages))
		{
			foreach ($languages as $language)
			{
				#Process for #__helpdeskpro_categories table							
				$prefix = $language->sef;
				$fields = array_keys($db->getTableColumns('#__helpdeskpro_categories'));

				if (!in_array('title_' . $prefix, $fields))
				{
					$fieldName = 'title_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_categories` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();

					$fieldName = 'description_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_categories` ADD  `$fieldName` TEXT NULL;";
					$db->setQuery($sql);
					$db->execute();
				}

				if (!in_array('alias_' . $prefix, $fields))
				{
					$fieldName = 'alias_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_categories` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();
				}

				#Process for #__helpdeskpro_statuses table
				$fields = array_keys($db->getTableColumns('#__helpdeskpro_statuses'));
				if (!in_array('title_' . $prefix, $fields))
				{
					$fieldName = 'title_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_statuses` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();
				}

				#Process for #__helpdeskpro_priorities table
				$fields = array_keys($db->getTableColumns('#__helpdeskpro_priorities'));
				if (!in_array('title_' . $prefix, $fields))
				{
					$fieldName = 'title_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_priorities` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();
				}

				#Process for #__helpdeskpro_fields table
				$fields = array_keys($db->getTableColumns('#__helpdeskpro_fields'));
				if (!in_array('title_' . $prefix, $fields))
				{
					$fieldName = 'title_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_fields` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();

					$fieldName = 'description_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_fields` ADD  `$fieldName` TEXT NULL;";
					$db->setQuery($sql);
					$db->execute();

					$fieldName = 'values_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_fields` ADD  `$fieldName` TEXT NULL;";
					$db->setQuery($sql);
					$db->execute();

					$fieldName = 'default_values_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_fields` ADD  `$fieldName` TEXT NULL;";
					$db->setQuery($sql);
					$db->execute();
				}

				// Process for #__helpdeskpro_articles tabl
				$fields = array_keys($db->getTableColumns('#__helpdeskpro_articles'));

				if (!in_array('title_' . $prefix, $fields))
				{
					$fieldName = 'title_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_articles` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();

					$fieldName = 'text_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_articles` ADD  `$fieldName` TEXT NULL;";
					$db->setQuery($sql);
					$db->execute();
				}

				if (!in_array('alias_' . $prefix, $fields))
				{
					$fieldName = 'alias_' . $prefix;
					$sql       = "ALTER TABLE  `#__helpdeskpro_articles` ADD  `$fieldName` VARCHAR( 255 );";
					$db->setQuery($sql);
					$db->execute();
				}
			}
		}
	}

	/**
	 * Process BB code for the given message
	 *
	 * @param   string  $message
	 *
	 * @return string
	 */
	public static function processBBCode($message)
	{
		require_once JPATH_ROOT . '/administrator/components/com_helpdeskpro/libraries/bbcodeparser.php';

		$config = self::getConfig();

		if (!$config->use_html_editor)
		{
			$message = nl2br($message);
		}

		return \BBCodeParser::parse($message);
	}

	/**
	 *  Method to add ticket or comment attachments to mailer for sending emails
	 *
	 * @param   \JMail  $mailer
	 * @param   object  $row
	 */
	protected static function addAttachmentsToMailer($mailer, $row)
	{
		$originalFileNames = explode('|', $row->original_filenames);
		$attachments       = explode('|', $row->attachments);

		for ($i = 0, $n = count($attachments); $i < $n; $i++)
		{
			$attachment       = $attachments[$i];
			$originalFileName = $originalFileNames[$i];

			if (file_exists(JPATH_ROOT . '/media/com_helpdeskpro/attachments/' . $attachment))
			{
				$mailer->addAttachment(JPATH_ROOT . '/media/com_helpdeskpro/attachments/' . $attachment, $originalFileName);
			}
		}
	}

	/**
	 * Send email to super administrator and user
	 *
	 * @param   object  $row     The message object
	 * @param   object  $ticket  The ticket object
	 * @param   object  $config
	 */
	public static function sendTicketUpdatedEmailToCustomer($row, $ticket, $config)
	{
		$user        = Factory::getUser();
		$mailer      = static::getMailer();
		$db          = Factory::getDbo();
		$message     = self::getEmailMessages();
		$fieldSuffix = self::getFieldSuffix($ticket->language);

		$query = $db->getQuery(true)
			->select('name')
			->from('#__users')
			->where('id = ' . (int) $row->user_id);
		$db->setQuery($query);
		$manageName = $db->loadResult();

		$replaces = self::getCommonTicketTags($ticket, $config);

		if ($config->use_html_editor)
		{
			$replaces['ticket_comment'] = $row->message;
		}
		else
		{
			$replaces['ticket_comment'] = nl2br($row->message);
		}

		$replaces['manager_name'] = $manageName;

		if ($fieldSuffix && $message->{'ticket_updated_user_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'ticket_updated_user_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->ticket_updated_user_email_subject;
		}

		if ($fieldSuffix && strlen(strip_tags($message->{'ticket_updated_user_email_body' . $fieldSuffix})))
		{
			$body = $message->{'ticket_updated_user_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->ticket_updated_user_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$key     = strtoupper($key);
			$body    = str_replace("[$key]", $value, $body);
			$subject = str_replace("[$key]", $value, $subject);
		}

		if ($config->notify_manager_when_staff_reply && ($ticket->staff_id == $user->id))
		{
			// Staff reply to ticket
			$emails = static::getTicketNotificationEmails($ticket);
			$mailer->addBcc($emails);
		}
		elseif ($config->notify_other_managers_when_a_manager_reply && $ticket->staff_id != $user->id)
		{
			// Admin or manager reply to a ticket
			$emails = static::getTicketNotificationEmails($ticket);

			// Exclude email of the current manager from receiving notification
			$emails = array_diff($emails, [$user->email]);

			if (count($emails))
			{
				$mailer->addBcc($emails);
			}
		}

		// Add ticket attachments to email if configured
		if ($config->send_ticket_attachments_to_email && $row->attachments)
		{
			static::addAttachmentsToMailer($mailer, $row);
		}

		if ($ticket->user_id)
		{
			$userEmail = static::getUserEmail($ticket->user_id);

			if ($userEmail != $ticket->email)
			{
				$ticket->email = $userEmail;

				$query->clear()
					->update('#__helpdeskpro_tickets')
					->set('email = ' . $db->quote($userEmail))
					->where('user_id = ' . $ticket->user_id);
				$db->setQuery($query)
					->execute();
			}
		}


		static::send($mailer, [$ticket->email], $subject, $body);
	}

	/**
	 * Send email to super administrator and user
	 *
	 * @param   object  $row     The message object
	 * @param   object  $ticket  The ticket object
	 * @param   object  $config
	 */
	public static function sendTicketUpdatedEmailToManagers($row, $ticket, $config)
	{
		$mailer      = static::getMailer();
		$message     = self::getEmailMessages();
		$fieldSuffix = self::getFieldSuffix($ticket->language);

		$replaces = self::getCommonTicketTags($ticket, $config);

		if ($config->use_html_editor)
		{
			$replaces['ticket_comment'] = $row->message;
		}
		else
		{
			$replaces['ticket_comment'] = nl2br($row->message);
		}

		$emails = static::getTicketNotificationEmails($ticket, true);

		if ($message->{'ticket_updated_admin_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'ticket_updated_admin_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->ticket_updated_admin_email_subject;
		}

		if (strlen(strip_tags($message->{'ticket_updated_admin_email_body' . $fieldSuffix})))
		{
			$body = $message->{'ticket_updated_admin_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->ticket_updated_admin_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$key     = strtoupper($key);
			$body    = str_replace("[$key]", $value, $body);
			$subject = str_replace("[$key]", $value, $subject);
		}

		// Add ticket attachments to email if configured
		if ($config->send_ticket_attachments_to_email && $row->attachments)
		{
			static::addAttachmentsToMailer($mailer, $row);
		}

		static::send($mailer, $emails, $subject, $body);
	}

	/**
	 * Send email to super administrator and user
	 *
	 * @param   object  $row     The message object
	 * @param   object  $ticket  The ticket object
	 * @param   object  $config
	 */
	public static function sendNewTicketNotificationEmails($row, $config)
	{
		$mailer      = static::getMailer();
		$message     = self::getEmailMessages();
		$fieldSuffix = self::getFieldSuffix($row->language);

		$replaces = self::getCommonTicketTags($row, $config);

		$emails = static::getTicketNotificationEmails($row);

		if ($message->{'new_ticket_admin_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'new_ticket_admin_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->new_ticket_admin_email_subject;
		}

		if (strlen(strip_tags($message->{'new_ticket_admin_email_body' . $fieldSuffix})))
		{
			$body = $message->{'new_ticket_admin_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->new_ticket_admin_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$body    = str_ireplace("[$key]", $value, $body);
			$subject = str_ireplace("[$key]", $value, $subject);
		}

		// Add ticket attachments to email if configured
		if ($config->send_ticket_attachments_to_email && $row->attachments)
		{
			static::addAttachmentsToMailer($mailer, $row);
		}

		static::send($mailer, $emails, $subject, $body);

		$mailer->clearAllRecipients();
		$mailer->clearAttachments();

		if (!MailHelper::isEmailAddress($row->email))
		{
			return;
		}

		//Send email to user
		if ($message->{'new_ticket_user_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'new_ticket_user_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->new_ticket_user_email_subject;
		}

		if (strlen(strip_tags($message->{'new_ticket_user_email_body' . $fieldSuffix})))
		{
			$body = $message->{'new_ticket_user_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->new_ticket_user_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$body    = str_ireplace("[$key]", $value, $body);
			$subject = str_ireplace("[$key]", $value, $subject);
		}

		if ($row->user_id)
		{
			$userEmail = static::getUserEmail($row->user_id);

			if ($userEmail != $row->email)
			{
				$row->email = $userEmail;

				$db    = Factory::getDbo();
				$query = $db->getQuery(true)
					->update('#__helpdeskpro_tickets')
					->set('email = ' . $db->quote($userEmail))
					->where('user_id = ' . $row->user_id);
				$db->setQuery($query)
					->execute();
			}
		}

		static::send($mailer, [$row->email], $subject, $body);
	}

	/**
	 * Send Ticket assigned email
	 *
	 * @param   object  $row
	 * @param   object  $config
	 */
	public static function sendTicketAssignedEmails($row, $config)
	{
		if (!$row->staff_id)
		{
			return;
		}

		$mailer                   = static::getMailer();
		$message                  = self::getEmailMessages();
		$fieldSuffix              = self::getFieldSuffix($row->language);
		$replaces                 = self::getCommonTicketTags($row, $config);
		$replaces['MANAGER_NAME'] = Factory::getUser()->name;

		if ($message->{'customer_ticket_assigned_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'customer_ticket_assigned_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->customer_ticket_assigned_email_subject;
		}

		if (strlen(strip_tags($message->{'customer_ticket_assigned_email_body' . $fieldSuffix})))
		{
			$body = $message->{'customer_ticket_assigned_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->customer_ticket_assigned_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$body    = str_ireplace("[$key]", $value, $body);
			$subject = str_ireplace("[$key]", $value, $subject);
		}

		static::send($mailer, [$row->email], $subject, $body);

		$mailer->clearAllRecipients();

		// Get staff email
		$db    = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('email')
			->from('#__users')
			->where('id = ' . $row->staff_id);
		$db->setQuery($query);
		$staffEmail = $db->loadResult();

		if (!MailHelper::isEmailAddress($staffEmail))
		{
			return;
		}

		//Send email to staff
		if ($message->{'ticket_assiged_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'ticket_assiged_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->ticket_assiged_email_subject;
		}

		if (strlen(strip_tags($message->{'ticket_assiged_email_body' . $fieldSuffix})))
		{
			$body = $message->{'ticket_assiged_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->ticket_assiged_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$body    = str_ireplace("[$key]", $value, $body);
			$subject = str_ireplace("[$key]", $value, $subject);
		}

		static::send($mailer, [$staffEmail], $subject, $body);
	}


	/**
	 * Send ticket closed email to customer
	 *
	 * @param $row
	 * @param $config
	 */
	public static function sendTicketClosedEmail($row, $config)
	{
		$user = Factory::getUser();

		$mailer      = static::getMailer();
		$message     = self::getEmailMessages();
		$fieldSuffix = self::getFieldSuffix($row->language);
		$replaces    = self::getCommonTicketTags($row, $config);

		// Customer close ticket, sending email to managers
		if ($user->id == $row->user_id)
		{
			if ($message->{'manager_ticket_closed_email_subject' . $fieldSuffix})
			{
				$subject = $message->{'manager_ticket_closed_email_subject' . $fieldSuffix};
			}
			else
			{
				$subject = $message->manager_ticket_closed_email_subject;
			}

			if (strlen(strip_tags($message->{'manager_ticket_closed_email_body' . $fieldSuffix})))
			{
				$body = $message->{'manager_ticket_closed_email_body' . $fieldSuffix};
			}
			else
			{
				$body = $message->manager_ticket_closed_email_body;
			}

			foreach ($replaces as $key => $value)
			{
				$body    = str_ireplace("[$key]", $value, $body);
				$subject = str_ireplace("[$key]", $value, $subject);
			}

			// Get all managers + staff email
			$emails = static::getTicketNotificationEmails($row, true);

			static::send($mailer, $emails, $subject, $body);

			return;
		}

		// Manager or staff closes ticket, send notification email to customer
		$replaces['MANAGER_NAME'] = Factory::getUser()->name;

		if ($message->{'customer_ticket_closed_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'customer_ticket_closed_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->customer_ticket_closed_email_subject;
		}

		if (strlen(strip_tags($message->{'customer_ticket_closed_email_body' . $fieldSuffix})))
		{
			$body = $message->{'customer_ticket_closed_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->customer_ticket_closed_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$body    = str_ireplace("[$key]", $value, $body);
			$subject = str_ireplace("[$key]", $value, $subject);
		}

		static::send($mailer, [$row->email], $subject, $body);
	}

	/**
	 * Send ticket status change email to customer
	 *
	 * @param $row
	 * @param $config
	 */
	public static function sendTicketStatusChangeEmail($row, $oldStatus, $newStatus, $config)
	{
		$user = Factory::getUser();

		$mailer      = static::getMailer();
		$db          = Factory::getDbo();
		$message     = self::getEmailMessages();
		$fieldSuffix = self::getFieldSuffix($row->language);
		$replaces    = self::getCommonTicketTags($row, $config);

		$query = $db->getQuery(true)
			->select('title')
			->from('#__helpdeskpro_statuses')
			->where('id = ' . (int) $oldStatus);

		if ($fieldSuffix)
		{
			DatabaseUtils::getMultilingualFields($query, ['title'], $fieldSuffix);
		}

		$db->setQuery($query);

		$replaces['old_status'] = $db->loadResult();

		$query->clear('where')
			->where('id = ' . (int) $newStatus);
		$db->setQuery($query);

		$replaces['new_status'] = $db->loadResult();

		// Customer close ticket, sending email to managers
		if ($user->id == $row->user_id)
		{
			if ($message->{'manager_ticket_status_changed_email_subject' . $fieldSuffix})
			{
				$subject = $message->{'manager_ticket_status_changed_email_subject' . $fieldSuffix};
			}
			else
			{
				$subject = $message->manager_ticket_status_changed_email_subject;
			}

			if (strlen(strip_tags($message->{'manager_ticket_status_changed_email_body' . $fieldSuffix})))
			{
				$body = $message->{'manager_ticket_status_changed_email_body' . $fieldSuffix};
			}
			else
			{
				$body = $message->manager_ticket_status_changed_email_body;
			}

			foreach ($replaces as $key => $value)
			{
				$body    = str_ireplace("[$key]", $value, $body);
				$subject = str_ireplace("[$key]", $value, $subject);
			}

			// Get all managers + staff emails
			$emails = static::getTicketNotificationEmails($row, true);

			static::send($mailer, $emails, $subject, $body);

			return;
		}

		// Manager or staff change ticket status, send notification email to customer
		$replaces['MANAGER_NAME'] = Factory::getUser()->name;

		if ($message->{'customer_ticket_status_changed_email_subject' . $fieldSuffix})
		{
			$subject = $message->{'customer_ticket_status_changed_email_subject' . $fieldSuffix};
		}
		else
		{
			$subject = $message->customer_ticket_status_changed_email_subject;
		}

		if (strlen(strip_tags($message->{'customer_ticket_status_changed_email_body' . $fieldSuffix})))
		{
			$body = $message->{'customer_ticket_status_changed_email_body' . $fieldSuffix};
		}
		else
		{
			$body = $message->customer_ticket_status_changed_email_body;
		}

		foreach ($replaces as $key => $value)
		{
			$body    = str_ireplace("[$key]", $value, $body);
			$subject = str_ireplace("[$key]", $value, $subject);
		}

		static::send($mailer, [$row->email], $subject, $body);
	}

	/**
	 * Get common tags related to ticket and use it for sending emails
	 *
	 * @param   \OSSolution\HelpdeskPro\Admin\Table\Ticket  $row
	 * @param   \stdClass                                   $config
	 *
	 * @return array
	 */
	public static function getCommonTicketTags($row, $config)
	{
		$siteUrl     = Uri::root();
		$fieldSuffix = self::getFieldSuffix($row->language);
		$db          = Factory::getDbo();
		$query       = $db->getQuery(true);
		$replaces    = [];

		$replaces['ticket_id']      = $row->id;
		$replaces['ticket_subject'] = $row->subject;
		$replaces['name']           = $row->name;
		$replaces['email']          = $row->email;

		if ($row->staff_id)
		{
			$query->clear()
				->select('name')
				->from('#__users')
				->where('id = ' . (int) $row->staff_id);
			$db->setQuery($query);
			$replaces['staff_name'] = $db->loadResult();
		}
		else
		{
			$replaces['staff_name'] = '';
		}

		if ($config->use_html_editor)
		{
			$replaces['ticket_message'] = $row->message;
		}
		else
		{
			$replaces['ticket_message'] = nl2br($row->message);
		}

		$replaces['frontend_link']               = $siteUrl . RouteHelper::getTicketRoute($row->id);
		$replaces['backend_link']                = $siteUrl . 'administrator/index.php?option=com_helpdeskpro&view=ticket&id=' . $row->id;
		$replaces['frontend_link_without_login'] = $siteUrl . RouteHelper::getTicketRoute($row->ticket_code, false);

		$query->clear()
			->select('id, name, title')
			->from('#__helpdeskpro_fields')
			->where('published=1')
			->where('(category_id = -1 OR id IN (SELECT field_id FROM #__helpdeskpro_field_categories WHERE category_id=' . $row->category_id . '))')
			->order('ordering');
		$db->setQuery($query);
		$rowFields = $db->loadObjectList();
		$fields    = [];

		for ($i = 0, $n = count($rowFields); $i < $n; $i++)
		{
			$rowField              = $rowFields[$i];
			$fields[$rowField->id] = $rowField->name;
		}

		$query->clear()
			->select('*')
			->from('#__helpdeskpro_field_value')
			->where('ticket_id = ' . $row->id);
		$db->setQuery($query);
		$rowValues = $db->loadObjectList();

		for ($i = 0, $n = count($rowValues); $i < $n; $i++)
		{
			$rowValue                               = $rowValues[$i];
			$replaces[$fields[$rowValue->field_id]] = $rowValue->field_value;
		}

		$query->clear()
			->select('name')
			->from('#__helpdeskpro_fields');
		$db->setQuery($query);
		$fields = $db->loadColumn();

		foreach ($fields as $field)
		{
			if (!isset($replaces[$field]))
			{
				$replaces[$field] = '';
			}
		}

		$query->clear()
			->select($db->quoteName('title' . $fieldSuffix))
			->from('#__helpdeskpro_categories')
			->where('id = ' . $row->category_id);
		$db->setQuery($query);
		$replaces['ticket_category'] = $replaces['category_title'] = $db->loadResult();

		// Ticket status
		$query->clear()
			->select($db->quoteName('title' . $fieldSuffix))
			->from('#__helpdeskpro_statuses')
			->where('id = ' . (int) $row->status_id);
		$db->setQuery($query);
		$replaces['ticket_status'] = $db->loadResult();

		// Ticket priority
		$query->clear()
			->select($db->quoteName('title' . $fieldSuffix))
			->from('#__helpdeskpro_priorities')
			->where('id = ' . (int) $row->priority_id);
		$db->setQuery($query);
		$replaces['ticket_priority'] = $db->loadResult();

		return $replaces;
	}

	/**
	 *
	 * Function to get all available languages except the default language
	 * @return array object list
	 */
	public static function getLanguages()
	{
		$db      = Factory::getDbo();
		$query   = $db->getQuery(true);
		$default = self::getDefaultLanguage();
		$query->select('lang_id, lang_code, title, `sef`')
			->from('#__languages')
			->where('published = 1')
			->where('lang_code != "' . $default . '"')
			->order('ordering');
		$db->setQuery($query);
		$languages = $db->loadObjectList();

		return $languages;
	}

	/**
	 * Get front-end default language
	 * @return string
	 */
	public static function getDefaultLanguage()
	{
		$params = ComponentHelper::getParams('com_languages');

		return $params->get('site', 'en-GB');
	}

	/**
	 * Get formatted file size of a file
	 *
	 * @param   string  $filePath
	 *
	 * @return string
	 */
	public static function getSize($filePath)
	{
		$kb   = 1024;
		$mb   = 1024 * $kb;
		$gb   = 1024 * $mb;
		$tb   = 1024 * $gb;
		$size = @filesize($filePath);

		if ($size)
		{
			if ($size < $kb)
			{
				$final    = round($size, 2);
				$fileSize = $final . ' ' . 'Byte';
			}
			elseif ($size < $mb)
			{
				$final    = round($size / $kb, 2);
				$fileSize = $final . ' ' . 'KB';
			}
			elseif ($size < $gb)
			{
				$final    = round($size / $mb, 2);
				$fileSize = $final . ' ' . 'MB';
			}
			elseif ($size < $tb)
			{
				$final    = round($size / $gb, 2);
				$fileSize = $final . ' ' . 'GB';
			}
			else
			{
				$final    = round($size / $tb, 2);
				$fileSize = $final . ' ' . 'TB';
			}
		}
		else
		{
			if ($size == 0)
			{
				$fileSize = 'EMPTY';
			}
			else
			{
				$fileSize = 'ERROR';
			}
		}

		return $fileSize;
	}

	/**
	 * Store ticket from input data
	 *
	 * @param   array  $data
	 *
	 * @return bool
	 */
	public static function storeTicket($data)
	{
		jimport('joomla.user.helper');

		$container = \OSL\Container\Container::getInstance('com_helpdeskpro');

		$db     = $container->db;
		$user   = $container->user;
		$config = Helper::getConfig();

		$row = $container->factory->createTable('Ticket', $db);
		$row->bind($data);

		if ($user->get('id'))
		{
			$row->user_id = $user->get('id');
		}
		else
		{
			$sql = 'SELECT id FROM #__users WHERE email=' . $db->quote($data['email']);
			$db->setQuery($sql);
			$row->user_id = $db->loadResult();
		}

		$row->status_id = $config->new_ticket_status_id;

		while (true)
		{
			$ticketCode = strtolower(UserHelper::genRandomPassword(10));
			$sql        = 'SELECT COUNT(*) FROM #__helpdeskpro_tickets WHERE ticket_code=' . $db->quote($ticketCode);
			$db->setQuery($sql);
			$total = $db->loadResult();

			if (!$total)
			{
				break;
			}
		}

		$row->ticket_code  = $ticketCode;
		$row->created_date = $row->modified_date = gmdate('Y-m-d H:i:s');
		$row->store(); //Store custom fields information for this ticket	

		Helper::sendNewTicketNotificationEmails($row, $config);

		return true;
	}

	/**
	 * Get email of user
	 *
	 * @param   int  $userId
	 *
	 * @return string
	 */
	public static function getUserEmail($userId)
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('email')
			->from('#__users')
			->where('id = ' . (int) $userId);
		$db->setQuery($query);

		return $db->loadResult();
	}

	/**
	 * Get avatar of user
	 *
	 * @param   int  $userId
	 *
	 * @return string
	 */
	public static function getUserAvatar($userId)
	{
		static $avatars = [];

		if (!isset($avatars[$userId]))
		{
			// Default avatar
			$avatars[$userId] = 'media/com_helpdeskpro/assets/images/icons/icon-user.jpeg';

			$db    = Factory::getDbo();
			$query = $db->getQuery(true);

			if (ComponentHelper::isInstalled('com_comprofiler') && ComponentHelper::isEnabled('com_comprofiler'))
			{
				$query->select('avatar')
					->from('#__comprofiler')
					->where('user_id=' . $userId . ' AND avatarapproved = 1');
				$db->setQuery($query);
				$avatar = $db->loadResult();

				if ($avatar && file_exists(JPATH_ROOT . '/images/comprofiler/' . $avatar))
				{
					$avatars[$userId] = 'images/comprofiler/' . $avatar;
				}
			}
			elseif (ComponentHelper::isInstalled('com_kunena') && ComponentHelper::isEnabled('com_kunena'))
			{
				$query->select('avatar')
					->from('#__kunena_users')
					->where('userid=' . $userId);
				$db->setQuery($query);
				$avatar = $db->loadResult();

				if ($avatar && file_exists(JPATH_ROOT . '/media/kunena/avatars/resized/size72/' . $avatar))
				{
					$avatars[$userId] = 'media/kunena/avatars/resized/size72/' . $avatar;
				}
			}
		}

		return $avatars[$userId];
	}


	/**
	 * Get Notification Emails for a given ticket
	 *
	 * @param   \Joomla\CMS\Table\Table  $ticket
	 *
	 * @return array
	 */
	public static function getTicketNotificationEmails($ticket, $includeStaffEmail = false)
	{
		$config = static::getConfig();
		$db     = Factory::getDbo();
		$query  = $db->getQuery(true)
			->select('managers')
			->from('#__helpdeskpro_categories')
			->where('id = ' . (int) $ticket->category_id);
		$db->setQuery($query);
		$managers = trim($db->loadResult());

		if ($managers)
		{
			$managers = explode(',', $managers);
			$managers = array_map('trim', $managers);
			$query->clear()
				->select('email')
				->from('#__users')
				->where('username IN ("' . implode('","', $managers) . '")');
			$db->setQuery($query);
			$emails = $db->loadColumn();
		}
		else
		{
			$config = static::getConfig();
			$emails = array_map('trim', explode(',', $config->notification_emails));
		}

		if ($includeStaffEmail && $config->notify_staff_when_customer_reply && $ticket->staff_id)
		{
			$db    = Factory::getDbo();
			$query = $db->getQuery(true)
				->select('email')
				->from('#__users')
				->where('id = ' . (int) $ticket->staff_id);
			$db->setQuery($query);
			$email = $db->loadResult();

			if (MailHelper::isEmailAddress($email))
			{
				$emails[] = $email;
			}
		}

		return $emails;
	}

	/**
	 * Create and initialize mailer object from configuration data
	 *
	 * @return \JMail
	 */
	public static function getMailer()
	{
		$mailer = Factory::getMailer();
		$config = static::getConfig();

		if ($config->reply_to_email)
		{
			$mailer->addReplyTo($config->reply_to_email);
		}

		if ($config->from_name)
		{
			$fromName = $config->from_name;
		}
		else
		{
			$fromName = Factory::getConfig()->get('fromname');
		}

		if ($config->from_email)
		{
			$fromEmail = $config->from_email;
		}
		else
		{
			$fromEmail = Factory::getConfig()->get('mailfrom');
		}

		$mailer->setSender([$fromEmail, $fromName]);

		$mailer->isHtml(true);

		return $mailer;
	}

	/**
	 * Process sending after all the data has been initialized
	 *
	 * @param   \JMail  $mailer
	 * @param   array   $emails
	 * @param   string  $subject
	 * @param   string  $body
	 *
	 */
	public static function send($mailer, $emails, $subject, $body)
	{
		if (empty($subject))
		{
			return;
		}

		$emails = (array) $emails;

		$emails = array_map('trim', $emails);

		for ($i = 0, $n = count($emails); $i < $n; $i++)
		{
			if (!MailHelper::isEmailAddress($emails[$i]))
			{
				unset($emails[$i]);
			}
		}

		$emails = array_unique($emails);

		if (count($emails) == 0)
		{
			return;
		}

		$email = $emails[0];
		$mailer->addRecipient($email);

		if (count($emails) > 1)
		{
			unset($emails[0]);
			$bccEmails = $emails;
			$mailer->addBcc($bccEmails);
		}

		$body = static::convertImgTags($body);

		try
		{
			$mailer->setSubject($subject)
				->setBody($body)
				->Send();
		}
		catch (\Exception $e)
		{
			Factory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
		}
	}

	/**
	 * Convert all img tags to use absolute URL
	 *
	 * @param   string  $text
	 *
	 * @return string
	 */
	public static function convertImgTags($text)
	{
		$app = Factory::getApplication();

		$siteUrl    = Uri::root();
		$rootURL    = rtrim(Uri::root(), '/');
		$subpathURL = Uri::root(true);

		if (!empty($subpathURL) && ($subpathURL != '/'))
		{
			$rootURL = substr($rootURL, 0, -1 * strlen($subpathURL));
		}

		// Replace index.php URI by SEF URI.
		if (strpos($text, 'href="index.php?') !== false)
		{
			preg_match_all('#href="index.php\?([^"]+)"#m', $text, $matches);

			foreach ($matches[1] as $urlQueryString)
			{

				if ($app->isClient('site'))
				{
					$text = str_replace(
						'href="index.php?' . $urlQueryString . '"',
						'href="' . $rootURL . Route::_('index.php?' . $urlQueryString) . '"',
						$text
					);
				}
				else
				{
					$text = str_replace(
						'href="index.php?' . $urlQueryString . '"',
						'href="' . $siteUrl . 'index.php?' . $urlQueryString . '"',
						$text
					);
				}
			}
		}

		$patterns     = [];
		$replacements = [];
		$i            = 0;
		$src_exp      = "/src=\"(.*?)\"/";
		$link_exp     = "[^http:\/\/www\.|^www\.|^https:\/\/|^http:\/\/]";

		preg_match_all($src_exp, $text, $out, PREG_SET_ORDER);

		foreach ($out as $val)
		{
			$links = preg_match($link_exp, $val[1], $match, PREG_OFFSET_CAPTURE);

			if ($links == '0')
			{
				$patterns[$i]     = $val[1];
				$patterns[$i]     = "\"$val[1]";
				$replacements[$i] = $siteUrl . $val[1];
				$replacements[$i] = "\"$replacements[$i]";
			}

			$i++;
		}

		$text = str_replace($patterns, $replacements, $text);

		return $text;
	}
}