<?php
/**
 * @package    VP Advanced User
 * @author     Abhishek Das <info@virtueplanet.com>
 * @copyright  Copyright (C) 2012-2019 VirtuePlanet Services LLP. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       https://www.virtueplanet.com
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;

/**
 * VPAdvancedUserModelData model.
 *
 * @since  1.0
 */
class VPAdvancedUserModelData extends JModelLegacy
{
	public $fields = array();
	
	protected $data = array();

	/**
	 * Method to get the form.
	 *
	 * @return  SimpleXMLElement   A SimpleXMLElement object on success, false on failure
	 *
	 * @since    1.0
	 */
	public function getForm($for)
	{
		JForm::addFieldPath(JPATH_ADMINISTRATOR . '/components/com_vpadvanceduser/models/fields');
		
		$items = $this->getFields($for);

		if($items === false)
		{
			$this->setError($this->getError());
			return false;
		}
		
		$app  = JFactory::getApplication();
		$form = new SimpleXMLElement('<form />');
		
		if(empty($items))
		{
			if($app->isSite() && $for == 'registration')
			{
				$fieldset = $form->addChild('fieldset');
				$fieldset->addAttribute('name', 'default');
				$fieldset->addAttribute('label', 'COM_USERS_REGISTRATION_DEFAULT_LABEL');
			
				$field = $fieldset->addChild('field');
				$field->addAttribute('name', 'captcha');
				$field->addAttribute('type', 'captcha');
				$field->addAttribute('label', 'COM_USERS_CAPTCHA_LABEL');
				$field->addAttribute('description', 'COM_USERS_CAPTCHA_DESC');
				$field->addAttribute('validate', 'captcha');

				return $form;
			}
			
			return null;
		}
		
		$fields = $form->addChild('fields');
		$fields->addAttribute('name', 'vpadvanceduserdata');
		
		foreach($items as $key => $item)
		{
			$registry = new Registry;
			
			if(!empty($item->params) && is_string($item->params))
			{
				$registry->loadString($item->params);
			}
			
			$item->params = $registry;
			
			if($key === 0 && $item->type != 'legend')
			{
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', 'default_fieldset');
				
				if(strtolower($for) != 'registration')
				{
					$fieldset->addAttribute('label', 'COM_VPADVANCEDUSER_DEFAULT_FIELDSET');
				}
			}
			
			if($item->type == 'legend')
			{
				$fieldset = $fields->addChild('fieldset');
				$fieldset->addAttribute('name', $item->name);
				$fieldset->addAttribute('label', $item->label);
				
				if(trim($item->description) != '')
				{
					$fieldset->addAttribute('description', $item->description);
				}
				
				continue;
			}
			
			$field = $fieldset->addChild('field');
			$field->addAttribute('name', $item->name);
			$field->addAttribute('type', $item->type);
			$field->addAttribute('label', $item->label);
			
			if(trim($item->description) != '')
			{
				$field->addAttribute('description', $item->description);
			}
			
			if(in_array($item->type, array('vplist', 'radio')))
			{
				$options = $item->params->get('options', '');
				
				if(!empty($options))
				{
					$options = strpos($options, ',') !== false ? explode(',', $options) : array($options);
					$options = array_map('trim', $options);
					
					foreach($options as $value => $text)
					{
						$option = $field->addChild('option', $text);
						$option->addAttribute('value', $value);
					}
				}
			}
			elseif($item->type == 'calendar')
			{
				$format = $item->params->get('format', '');
				$format = trim($format);
				
				if(!empty($format))
				{
					$field->addAttribute('format', $format);
				}
			}
			elseif($item->type == 'textarea')
			{
				$field->addAttribute('rows', 5);
			}
			
			if(in_array($item->type, array('list', 'file')))
			{
				if($item->params->get('multiple', 0))
				{
					$field->addAttribute('multiple', 'true');
				}
			}
			
			if($item->type == 'vptos')
			{
				if($article_id = $item->params->get('tos_article', 0))
				{
					$field->addAttribute('article_id', (int) $article_id);
				}
			}
			
			// Attributes applicable for all fields
			$attributes = array(
			    'default', 'filter', 'size', 'maxlength',
			    'required', 'readonly', 'disabled', 'autocomplete',
			    'hint', 'class', 'onchange', 'onclick'
			  );
			
			foreach($attributes as $attribute)
			{
				$value = $item->params->get($attribute, '');
				
				if(is_numeric($value) && ($value == 1 || ($attribute == 'autocomplete' && $value == 0)))
				{
					$field->addAttribute($attribute, (string) $value);
				}
				elseif(trim($value) != '')
				{
					$field->addAttribute($attribute, (string) $value);
				}
			}
		}
		
		if($app->isSite()  && $for == 'registration')
		{
			$fieldset = $form->addChild('fieldset');
			$fieldset->addAttribute('name', 'captcha_fieldset');
			
			$field = $fieldset->addChild('field');
			$field->addAttribute('name', 'captcha');
			$field->addAttribute('type', 'captcha');
			$field->addAttribute('label', 'COM_USERS_CAPTCHA_LABEL');
			$field->addAttribute('description', 'COM_USERS_CAPTCHA_DESC');
			$field->addAttribute('validate', 'captcha');
		}
		
		return $form;
	}
	
	public function getFields($for, $access = true, $enabled = true)
	{
		$for = strtolower(strval($for));
		
		if(empty($for) || !in_array($for, array('all', 'registration', 'profile')))
		{
			$this->setError('Invalid field request.');
			return false;
		}

		if(!isset($this->fields[$for]))
		{
			$db    = $this->getDbo();
			$query = $db->getQuery(true)
			            ->select('id, label, name, description, type, show_in_registration, show_in_profile, access, params, ordering, state, language')
			            ->from($db->quoteName('#__vpadvanceduser_fields'));
			
			if($for == 'registration')
			{
				$query->where($db->quoteName('show_in_registration') . ' = 1');
			}
			elseif($for == 'profile')
			{
				$query->where($db->quoteName('show_in_profile') . ' = 1');
			}
			
			if($access)
			{
				$user = JFactory::getUser();
				$query->where($db->quoteName('access') . ' IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')');
			}
			
			if($enabled)
			{
				$query->where($db->quoteName('state') . ' = 1');
			}

			$lang         = JFactory::getLanguage();
			$multi_lang   = JLanguageMultilang::isEnabled();
			$present_lang = $lang->getTag();
			$default_lang = $lang->getDefault();
			
			if($multi_lang)
			{
				$query->where('(' . $db->quoteName('language') . ' = ' . $db->quote($present_lang) . ' OR ' . $db->quoteName('language') . ' = ' . $db->quote('*') . ')');
			}
			else
			{
				$query->where('(' . $db->quoteName('language') . ' = ' . $db->quote($default_lang) . ' OR ' . $db->quoteName('language') . ' = ' . $db->quote('*') . ')');
			}
			
			$query->order($db->quoteName('ordering'));
			
			try
			{
				$db->setQuery($query);
				$fields = $db->loadObjectList();
			}
			catch(RuntimeException $e)
			{
				$this->setError($e->getMessage());
				return false;
			}
			
			$this->fields[$for] = $fields;
		}
		
		return $this->fields[$for];
	}

	/**
	 * Method to get all user data.
	 *
	 * @param   integer  $user_id  The id of the user.
	 *
	 * @return  mixed    Array on success, false on failure.
	 *
	 * @since    1.0
	 */
	public function getData($user_id)
	{
		$user_id = (int) $user_id;
		
		if(!isset($this->data[$user_id]))
		{
			$data = array();
			
			if($user_id > 0)
			{
				$db    = $this->getDbo();
				$query = $db->getQuery(true)
				            ->select($db->quoteName('data_key') . ',' . $db->quoteName('data_value'))
				            ->from($db->quoteName('#__vpadvanceduser_data'))
				            ->where($db->quoteName('user_id') . ' = ' . $user_id)
				            ->where($db->quoteName('data_key') . ' LIKE ' . $db->quote('data.%'))
				            ->order($db->quoteName('ordering'));
				
				try
				{
					$db->setQuery($query);
					$result = $db->loadRowList();
				}
				catch(RuntimeException $e)
				{
					$this->setError($e->getMessage());
					return false;
				}
				
				foreach($result as $field)
				{
					$key        = str_replace('data.', '', $field[0]);
					$data[$key] = @json_decode($field[1], true);
					
					if ($data[$key] === null)
					{
						$data[$key] = $field[1];
					}
					
					if($data[$key] && trim($data[$key]) == '')
					{
						$data[$key] = '';
					}
				}
			}

			$this->data[$user_id] = $data;
		}
		
		return $this->data[$user_id];
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   integer  $user_id  User ID.
	 * @param   array    $data     The form data.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   1.0
	 */
	public function save($user_id, $data)
	{
		$user_id = (int) $user_id;
		$data    = (array) $data;
		$array   = $data;
		
		if(empty($user_id))
		{
			$this->setError('Can not save custom user field data. No user id given.');
			return false;
		}
		
		try
		{
			$db    = $this->getDbo();
			$query = $db->getQuery(true);

				// Get available fields for data binding
				$query->select($db->quoteName('name'))
				      ->from($db->quoteName('#__vpadvanceduser_fields'))
				      ->order($db->quoteName('ordering'));
				$db->setQuery($query);
				$fields = $db->loadColumn();

			// Get previously saved records
			$query->clear()
			      ->select($db->quoteName('data_key') . ', ' . $db->quoteName('data_value'))
			      ->from($db->quoteName('#__vpadvanceduser_data'))
			      ->where($db->quoteName('user_id') . ' = ' . $user_id)
			      ->where($db->quoteName('data_key') . ' LIKE ' . $db->quote('data.%'))
			      ->order($db->quoteName('ordering'));
			$db->setQuery($query);
			$result = $db->loadObjectList('data_key');
			

			// Delete old records
			$query->clear()
			      ->delete($db->quoteName('#__vpadvanceduser_data'))
			      ->where($db->quoteName('user_id') . ' = ' . $user_id)
			      ->where($db->quoteName('data_key') . ' LIKE ' . $db->quote('data.%'));
			$db->setQuery($query);
			$db->execute();
			
			if(!empty($fields))
			{
				$array = array();
				
				foreach($fields as $field)
				{
					if(isset($data[$field]))
					{
						$array[$field] = $data[$field];
					}
					elseif(is_array($result) && isset($result['data.' . $field]))
					{
						$array[$field] = $result['data.' . $field]->data_value;
					}
				}
			}

			$tuples   = array();
			$ordering = 1;

			foreach ($array as $key => $value)
			{
				$value    = (is_array($value) || is_object($value) || (is_numeric($value) && strlen($value) > 5)) ? json_encode($value) : $value;
				$tuples[] = '(' . $user_id . ', ' . $db->quote('data.' . $key) . ', ' . $db->quote($value) . ', ' . ($ordering++) . ')';
			}

			$db->setQuery('INSERT INTO ' . $db->quoteName('#__vpadvanceduser_data') . ' VALUES ' . implode(', ', $tuples));
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			$this->setError($e->getMessage());
			return false;
		}
		
		return true;
	}
	
	/**
	* Method to delete all custom fields and social login records of an user
	* 
	* @param  integer  $user_id  Joomla user ID
	* 
	* @return boolean  False in case error/failure
	*/
	public function delete($user_id)
	{
		$user_id = (int) $user_id;
		
		if(empty($user_id))
		{
			$this->setError('Can not delete VP Advanced User custom field data. No user id given.');
			return false;
		}
		
		try
		{
			$db = JFactory::getDbo();
			$db->setQuery(
				'DELETE FROM #__vpadvanceduser_data WHERE user_id = ' . $user_id .
					" AND data_key LIKE 'data.%'"
			);
			$db->execute();
			
			$db->setQuery(
				'DELETE FROM #__vpadvanceduser_users WHERE user_id = ' . $user_id
			);
			$db->execute();
		}
		catch (Exception $e)
		{
			$this->setError($e->getMessage());
			return false;
		}
		
		return true;
	}
}
