<?
/**
 * @category    jold2jnew
 * @copyright    Copyright (C) 2012 NinjaForge. All rights reserved.
 * @license		GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
 * @link     	http://ninjaforge.com
 */

/**
 * Jold2Jnew class - It's not big, it's not clever and it sure as hell aint pretty but it kinda works, oh and its also not complete
 *
 * Helps you convert your joomla extension to 2.5, this class expects your extension to be installed in joomla
 *
 * USAGE:
 * $old2new = jold2jnew('com_extensionname');
 * $old2new->giveMe25love();
 *
 */
class jold2jnew 
{
	/**
	 * An array of frontend language strings to write to a new language file
	 *
	 * @var array
	 */
	protected $_language = array();

	/**
	 * the component were converting
	 *
	 * @var string
	 */
	protected $_component;

	/**
	 * the language string is already namespaced
	 *
	 * @var boolean
	 */
	protected $_namespaced;

	/**
	 * it is a nooku based extension
	 *
	 * @var boolean
	 */
	protected $_nooku;

	/**
	 * the directory to save updated files to
	 *
	 * @var string
	 */
	protected $_directory;

	/**
	 * the language string was quoted
	 *
	 * @var boolean
	 */
	protected $_quoted;

	protected $_callback;

	/**
	* Constructor 
	*
	* @param string		$component 		the name of the extension prepended with com_ (com_ninjaboard)
	* @param boolean 	$imNamespaced	the language strings are already namespaced
	* @param boolean 	$imNooku 		this is a nooku based extension
	* @param string		$directory		a relative directory to save the updated files to
	* @return void
	*/
	public function __construct($component = null, $imNamespaced = false, $imNooku = true, $directory = '/jold2jnew/')
	{
		// if no component is set do nothing
		if (!$component || strpos($component, 'com_') === false) 
			throw new Exception('You need to provide a component name prepended with com_');

		if (!JFolder::exists(JPATH_ADMINISTRATOR.'/components/'.$component))
			throw new Exception('The component doesnt appear to exist');

		$this->_namespaced 	= $imNamespaced;
		$this->_nooku		= $imNooku;
		$this->_directory 	= $directory;
		$this->_component   = $component;
	}

	/**
	 * Method for automaticly running everything in here
	 */
	public function giveMe25love()
	{
		$this->quoteLanguage();
		$this->replaceText();
	}

	/**
	 * Method for quoting the language strings
	 */
	public function quoteLanguage()
	{
		$folders = JFolder::folders(JPATH_ROOT.'/language/');
		// run the quoting again the frontend lang files
		$this->_saveQuoted($folders);

		// now the backend
		$folders = JFolder::folders(JPATH_ADMINISTRATOR.'/language/');
		$this->_saveQuoted($folders, true);
	}

	/**
	 * Method for replacing JText & @text (if nooku) with namespaced j2.5 language strings
	 */
	public function replaceText()
	{
		// run the admin files
		$path = '/administrator/components/'.$this->_component.'/';

		$files = JFolder::files(JPATH_ROOT.$path, '.php', true, true);
		$this->_saveReplacedText($files);

		$fpath = '/components/'.$this->_component.'/';
		// replace the frontend stuff
		if (JFolder::exists(JPATH_ROOT.$fpath)) {
			$files = JFolder::files(JPATH_ROOT.$fpath, '.php', true, true);
			$this->_saveReplacedText($files);
		}

		if ($this->_language)
			JFile::write(JPATH_ROOT.$this->_directory.'/en-GB-'.$this->_component.'.ini', implode('', $this->_language));
	}

	/**
 	 * Method for saving the quoted strings
 	 * @param array an array of folders
 	 * @param boolean true if frontend else false
 	 * @todo shouldnt we check for the old comment tag here too....
 	 */
	protected function _saveQuoted($folders, $frontend = true)
	{
		$path = ($frontend) ? '/language/' : '/administrator/language/';
		foreach ($folders as $folder) {
			//get the language file if it exists
			$file = $folder.'.'.$this->_component.'.ini';

			// if the file doesnt exist raise a warning and skip this folder
			if (!JFile::exists(JPATH_ROOT.$path.$folder.'/'.$file)) {
				JError::raiseNotice(0, $file.' does not appear to exists - skipping');
				continue;
			}

			// read the file into an array
			$content = file(JPATH_ROOT.$path.$folder.'/'.$file);

			//loop through our file array
			foreach ($content as $i => $line) {
				// trim seems flaky as hell
				ltrim(trim($line));

				// attempt to split our line
				$matches = preg_split('/[\=]+/', $line);

				// we should have 2 matches SOME STRING, some string
				if (count($matches) != 2) continue;

				// if the second string is only 1 char long, its empty
				if (strlen($matches[1]) == 1) {
					$content[$i] = $matches[0].'=""';
				} else {
					$content[$i] = $matches[0].'="'.trim($matches[1]).'"'."\n";
				}
			}

			//finally save the file in the new file directory flaky triming
			Jfile::write(JPATH_ROOT.$this->_directory.$path.$folder.'/'.$file, implode("",$content));
			$this->_quoted = true;
		}
	}

	/**
	 * Preg callback method
	 */
	protected function _pregCallback($matches)
	{
		if (isset($matches[0])) {
			// strip out the jtext bits
			$original = ($this->_callback == 'jtext') ? str_replace('JText::_(\'', '', $matches[0]) : str_replace('@text(\'', '', $matches[0]) ;

			$original = str_replace('\')', '', $original);
			// rebuild the string
			$new = ltrim(trim(strtoupper($original)));

			// keys have no business having punctuation or other random chars so strip them out (note they can have %)
			$new = str_replace(array('.', '\'','"','!', "?", '\\', "/", '*', '&', '«', '»', '[', ']', ')', '(', ':', ',', '{', '}'), '', $new);
			$new = strip_tags(htmlspecialchars($new));
			// keys have no business having spaces so replace with underscores
			$new = str_replace(' ', '_', trim($new));

			// if the keys are not namespaced then make it so
			if (!$this->_namespaced) $new = strtoupper($this->_component).'_'.$new;

			// generate the language file
			$this->_language[] = $new.'="'.$original.'"'."\n";

			// return the string with the new namespaced uppercase key
			return  ($this->_callback == 'jtext') ? 'JText::_(\''.$new.'\')' : '@text(\''.$new.'\')';

		}
	}

	/**
	 * Method for saving new files with replaced text
	 *
	 * @param array an array of files
	 */
	protected function _saveReplacedText($files)
	{
		// loop through each file in the folder
		foreach ($files as $file) {
	 		// i suck at regex, so there you go.....
	  		$sqpattern = '/(JText)(:)(:)(_)(\\()(\\\'.*?\\\')(\\))/';

			// read the file into an array
			$content = file($file);
			$this->_callback = 'jtext';

			//loop through our file array
			foreach ($content as $i => $line) {
				$content[$i] = preg_replace_callback($sqpattern, array($this, '_pregCallback'), $line);
			}
			//finally save the new file 
			JFile::write(JPATH_ROOT.$this->_directory.str_replace(JPATH_ROOT, '', $file), implode("", $content));

			// if we are nooku run the @text
			if ($this->_nooku) {

				$pattern = '/(@)(text)(\\()(\').*?(\')(\\))/';

				// make sure we run this on the files we have already done jtext with
				// read the file into an array
				$content = file(JPATH_ROOT.$this->_directory.'/'.str_replace(JPATH_ROOT, '', $file));

				$this->_callback = 'nooku';

				//loop through our file array
				foreach ($content as $i => $line) {
					$content[$i] = preg_replace_callback($pattern, array($this, '_pregCallback'), $line);
				}
				//finally save the new file 
				JFile::write(JPATH_ROOT.$this->_directory.str_replace(JPATH_ROOT, '',$file), implode("", $content));
			}
		}
	}
}