<?php
/***************************************************************
*  Copyright notice
*
*  (c) 2005-2007 Kasper Skaarhoj <kasperYYYY@typo3.com>
*  All rights reserved
*
*  This script is part of the TYPO3 project. The TYPO3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html.
*  A copy is found in the textfile GPL.txt and important notices to the license
*  from the author is found in LICENSE.txt distributed with these scripts.
*
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
 * This script extends the class, 'pibase'
 * 
 * @author	Franz Holzinger <kontakt@fholzinger.com>
 */
/**
 *
 */



require_once(PATH_tslib.'class.tslib_pibase.php');	// this class where this code should be put
require_once(PATH_BE_fh_library.'lib/class.tx_fhlibrary_flexform.php');
require_once(PATH_BE_fh_library.'lib/class.tx_fhlibrary_language.php');
require_once(PATH_BE_fh_library.'lib/class.tx_fhlibrary_system.php');
require_once(PATH_BE_fh_library.'lib/class.tx_fhlibrary_view.php');


/**
 * Base class for frontend plugins
 * Most modern frontend plugins are extension classes of this one.
 * This class contains functions which assists these plugins in creating lists, searching, displaying menus, page-browsing (next/previous/1/2/3) and handling links.
 * Functions are all prefixed "pi_" which is reserved for this class. Those functions can of course be overridden in the extension classes (that is the point...)
 * 
 *
 * @author	Franz Holzinger <kontakt@fholzinger.com>
 * @package FE BE library
 * @subpackage tslib
 */
class fhlibrary_pibase extends tslib_pibase {

	var $errorMessage;			// if an error occurs, set the output text here.

	/**
	 * Returns the values from the setup field or the field of the flexform converted into the value
	 * The default value will be used if no return value would be available.
	 * This can be used fine to get the CODE values or the display mode dependant if flexforms are used or not.
	 * And all others fields of the flexforms can be read.
	 * 
	 * @param	string		TypoScript configuration
	 * @param	string		extended TypoScript configuration
	 * @param	string		default value to use if the result would be empty
	 * @param	array		FlexForm data
	 * 						e.g. look at the name of the flexform which has been used in ext_tables.php
	 * 						$TCA['tt_content']['types']['list']['subtypes_addlist']['5']='pi_flexform';
	 * @param	string		Field name to extract. Can be given like "test/el/2/test/el/field_templateObject" where each part will dig a level deeper in the FlexForm data.
	 * @param	boolean		if flexforms are used or not
	 * @param	string		Sheet pointer, eg. "sDEF"
	 * @param	string		Language pointer, eg. "lDEF"
	 * @param	string		Value pointer, eg. "vDEF"
	 * @access public
	 *  
	 * example:
	 * 	$config['code'] = $this->pi_getSetupOrFFvalue(
	 * 					$this->conf['code'], 
	 * 					$this->conf['code.'], 
	 * 					$this->conf['defaultCode'], 
	 * 					$this->cObj->data['pi_flexform'],
	 * 					'display_mode',
	 * 					$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][TT_PRODUCTS_EXTkey]['useFlexforms']);
	 * 
	 * You have to call $this->pi_initPIflexForm(); before you call this method!
	 */
	function pi_getSetupOrFFvalue($code, $codeExt, $defaultCode, $T3FlexForm_array, $fieldName='display_mode', $useFlexforms=1, $sheet='sDEF',$lang='lDEF',$value='vDEF') {
		return tx_fhlibrary_flexform::getSetupOrFFvalue($this, $code, $codeExt, $defaultCode, $T3FlexForm_array, $fieldName, $useFlexforms);
	}


	/**
	 * returns the codes in the order in which they have to be processed
	 * This method should be overwritten
	 *
	 * @param       array          your code array
	 * @return      array
	 */
	function pi_sortCodes($codes)	{
		return ($codes);
	}


	/**
	 * Returns the help page with a mini guide how to setup the extension
	 * 
	 * @param	object		tslib_pibase object
	 * @param	string		path and filename of the template file
	 * 				
	 * @return	string		HTML to display the help page
	 * @access public
	 * 
	 * example:
	 * 	$content .= $this->pi_displayHelpPage($this->cObj->fileResource('EXT:'.TT_PRODUCTS_EXTkey.'/template/products_help.tmpl'));
	 * 	unset($this->errorMessage);
	 *
	 * @see fhlibrary_pibase::pi_displayHelpPage
	 */

	function pi_displayHelpPage($helpTemplate, $theCode='') {
		return tx_fhlibrary_view::displayHelpPage($this, $helpTemplate, $this->extKey, $this->errorMessage, $theCode);
	}


	/**
	 * Split Label function for front-end applications.
	 *
	 * @param	string		Key string. Accepts the "LLL:" prefix.
	 * @return	string		Label value, if any.
	 */
	function sL($input)	{
		return tx_fhlibrary_language::sL($input);
	}


	/**
	 * Calls user function
	 */
	function userProcess($mConfKey,$passVar)	{
		global $TSFE;

		if ($this->conf[$mConfKey])	{
			$funcConf = $this->conf[$mConfKey.'.'];
			$funcConf['parentObj']=&$this;
			$passVar = $TSFE->cObj->callUserFunction($this->conf[$mConfKey], $funcConf, $passVar);
		}
		return $passVar;
	} // userProcess


		// deprecated. use pi_loadTcaAdditions instead
	function pi_mergeExtendingTCAs($ext_keys){
		tx_fhlibrary_system::mergeExtendingTCAs($ext_keys);
	}


	/** pi_loadTcaAdditions($ext_keys)
	 *
	 *  In case you wrote an extension, that extends the table "$table", then
	 *  the TCA information for the additional fields will be merged with the "$table" TCA.
	 *
	 *  @param array Extension TCA's that should be merged.
	 */
	function pi_loadTcaAdditions($ext_keys){
		tx_fhlibrary_system::loadTcaAdditions($ext_keys);
	}


	/**
	 * Gets information for an extension, eg. version and most-recently-edited-script
	 *
	 * @param	string		Path to local extension folder
	 * @return	array		Information array (unless an error occured)
	 */
	function getExtensionInfo($path)	{
		return tx_fhlibrary_system::getExtensionInfo($path, $this->extKey);
	}


	/**
	 * Returns a linked string made from typoLink parameters.
	 *
	 * This function takes $label as a string, wraps it in a link-tag based on the $params string, which should contain data like that you would normally pass to the popular <LINK>-tag in the TSFE.
	 * Optionally you can supply $urlParameters which is an array with key/value pairs that are rawurlencoded and appended to the resulting url.
	 *
	 * @param	string		Text string being wrapped by the link.
	 * @param	string		Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file.
	 * @param	array		An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
	 * @param	string		Specific target set, if any. (Default is using the current)
	 * @param	array		Configuration
 	 * @return	string		The wrapped $label-text string
	 * @see getTypoLink_URL()
	 */
	function pi_getTypoLink($label,$params,$urlParameters=array(),$target='',$conf=array())	{
		$conf['parameter'] = $params;
		if ($target)	{
			$conf['target']=$target;
			$conf['extTarget']=$target;
		}
		if (is_array($urlParameters))	{
			if (count($urlParameters))	{
				$conf['additionalParams'].= t3lib_div::implodeArrayForUrl('',$urlParameters);
			}
		} else {
			$conf['additionalParams'].=$urlParameters;
		}
		$out = $this->cObj->typolink($label,$conf);
		return $out;
	}


	/**
	 * Returns the URL of a "typolink" create from the input parameter string, url-parameters and target
	 *
	 * @param	string		Link parameter; eg. "123" for page id, "kasperYYYY@typo3.com" for email address, "http://...." for URL, "fileadmin/blabla.txt" for file.
	 * @param	array		An array with key/value pairs representing URL parameters to set. Values NOT URL-encoded yet.
	 * @param	string		Specific target set, if any. (Default is using the current)
	 * @param	array		Configuration
	 * @return	string		The URL
	 * @see getTypoLink()
	 */
	function pi_getTypoLink_URL($params,$urlParameters=array(),$target='',$conf=array())	{
		$this->pi_getTypoLink('',$params,$urlParameters,$target,$conf);
		$rc = $this->cObj->lastTypoLinkUrl;
		return $rc;
	}

	/***************************
	 *
	 * Link functions
	 *
	 **************************/

	/**
	 * Get URL to some page.
	 * Returns the URL to page $id with $target and an array of additional url-parameters, $urlParameters
	 * Simple example: $this->pi_getPageLink(123) to get the URL for page-id 123.
	 *
	 * The function basically calls $this->cObj->getTypoLink_URL()
	 *
	 * @param	integer		Page id
	 * @param	string		Target value to use. Affects the &type-value of the URL, defaults to current.
	 * @param	array		Additional URL parameters to set (key/value pairs)
	 * @param	array		Configuration
	 * @return	string		The resulting URL
	 * @see pi_linkToPage()
	 */
	function pi_getPageLink($id,$target='',$urlParameters=array(),$conf=array())	{
		$rc = $this->pi_getTypoLink_URL($id,$urlParameters,$target, $conf);
		return $rc; // ?$target:$GLOBALS['TSFE']->sPre
	}


	/**
	 * Get External CObjects
	 */
	function getExternalCObject($mConfKey)	{
		if ($this->conf[$mConfKey] && $this->conf[$mConfKey.'.'])	{
			$this->cObj->regObj = &$this;
			return $this->cObj->cObjGetSingle($this->conf[$mConfKey],$this->conf[$mConfKey.'.'],'/'.$mConfKey.'/').'';
		}
	}

	function load_noLinkExtCobj()	{
		if ($this->conf['externalProcessing_final'] || is_array($this->conf['externalProcessing_final.']))	{	// If there is given another cObject for the final order confirmation template!
			$this->externalCObject = $this->getExternalCObject('externalProcessing_final');
		}
	} // load_noLinkExtCobj


	function pi_list_browseresults($showResultCount=1,$tableParams='',$wrapArr=array(), $pointerName = 'pointer', $hscText = TRUE)	{

			// Initializing variables:
		$pointer = intval($this->piVars[$pointerName]);
		$count = intval($this->internal['res_count']);
		$results_at_a_time = t3lib_div::intInRange($this->internal['results_at_a_time'],1,1000);
		$totalPages = ceil($count/$results_at_a_time);
		$maxPages = t3lib_div::intInRange($this->internal['maxPages'],1,100);
		$pi_isOnlyFields = $this->pi_isOnlyFields($this->pi_isOnlyFields);

			// $showResultCount determines how the results of the pagerowser will be shown.
			// If set to 0: only the result-browser will be shown
			//	 		 1: (default) the text "Displaying results..." and the result-browser will be shown.
			//	 		 2: only the text "Displaying results..." will be shown
		$showResultCount = intval($showResultCount);

			// if this is set, two links named "<< First" and "LAST >>" will be shown and point to the very first or last page.
		$showFirstLast = $this->internal['showFirstLast'];

			// if this has a value the "previous" button is always visible (will be forced if "showFirstLast" is set)
		$alwaysPrev = $showFirstLast?1:$this->pi_alwaysPrev;

		if (isset($this->internal['pagefloat'])) {
			if (strtoupper($this->internal['pagefloat']) == 'CENTER') {
				$pagefloat = ceil(($maxPages - 1)/2);
			} else {
				// pagefloat set as integer. 0 = left, value >= $this->internal['maxPages'] = right
				$pagefloat = t3lib_div::intInRange($this->internal['pagefloat'],-1,$maxPages-1);
			}
		} else {
			$pagefloat = -1; // pagefloat disabled
		}

			// default values for "traditional" wrapping with a table. Can be overwritten by vars from $wrapArr
		$wrapper['disabledLinkWrap'] = '<td nowrap="nowrap"><p>|</p></td>';
		$wrapper['inactiveLinkWrap'] = '<td nowrap="nowrap"><p>|</p></td>';
		$wrapper['activeLinkWrap'] = '<td'.$this->pi_classParam('browsebox-SCell').' nowrap="nowrap"><p>|</p></td>';
		$wrapper['browseLinksWrap'] = trim('<table '.$tableParams).'><tr>|</tr></table>';

		if ($this->internal['imagePath'])	{
			$onMouseOver = ($this->internal['imageOnMouseOver'] ? 'onmouseover="'.$this->internal['imageOnMouseOver'].'" ': ''); 		
			$onMouseOut = ($this->internal['imageOnMouseOut'] ? 'onmouseout="'.$this->internal['imageOnMouseOut'].'" ': ''); 		
			$onMouseOverActive = ($this->internal['imageActiveOnMouseOver'] ? 'onmouseover="'.$this->internal['imageActiveOnMouseOver'].'" ': ''); 		
			$onMouseOutActive = ($this->internal['imageActiveOnMouseOut'] ? 'onmouseout="'.$this->internal['imageActiveOnMouseOut'].'" ': ''); 		
			$wrapper['browseTextWrap'] = '<img src="'.$this->internal['imagePath'].$this->internal['imageFilemask'].'" '.$onMouseOver.$onMouseOut.'>';
			$wrapper['activeBrowseTextWrap'] = '<img src="'.$this->internal['imagePath'].$this->internal['imageActiveFilemask'].'" '.$onMouseOverActive.$onMouseOutActive.'>';
		}
		$wrapper['showResultsWrap'] = '<p>|</p>';
		$wrapper['browseBoxWrap'] = '
		<!--
			List browsing box:
		-->
		<div '.$this->pi_classParam('browsebox').'>
			|
		</div>';

			// now overwrite all entries in $wrapper which are also in $wrapArr
		$wrapper = array_merge($wrapper,$wrapArr);

		if ($showResultCount != 2) { //show pagebrowser
			if ($pagefloat > -1) {
				$lastPage = min($totalPages,max($pointer+1 + $pagefloat,$maxPages));
				$firstPage = max(0,$lastPage-$maxPages);
			} else {
				$firstPage = 0;
				$lastPage = t3lib_div::intInRange($totalPages,1,$maxPages);
			}
			$links=array();

				// Make browse-table/links:
			if ($showFirstLast) { // Link to first page
				if ($pointer>0)	{
					$links[]=$this->cObj->wrap($this->pi_linkTP_keepPIvars(htmlspecialchars($this->pi_getLL('pi_list_browseresults_first','<< First',$hscText)),array($pointerName => null),$pi_isOnlyFields),$wrapper['inactiveLinkWrap']);
				} else {
					$links[]=$this->cObj->wrap(htmlspecialchars($this->pi_getLL('pi_list_browseresults_first','<< First',$hscText)),$wrapper['disabledLinkWrap']);
				}
			}
			if ($alwaysPrev>=0)	{ // Link to previous page
				$previousText = $this->pi_getLL('pi_list_browseresults_prev','< Previous',$hscText);
				if ($pointer>0)	{
					$links[]=$this->cObj->wrap($this->pi_linkTP_keepPIvars($previousText,array($pointerName => ($pointer-1?$pointer-1:'')),$pi_isOnlyFields),$wrapper['inactiveLinkWrap']);
				} elseif ($alwaysPrev)	{
					$links[]=$this->cObj->wrap($previousText,$wrapper['disabledLinkWrap']);
				}
			}
			for($a=$firstPage;$a<$lastPage;$a++)	{ // Links to pages
				if ($this->internal['showRange']) {
					$pageText = (($a*$results_at_a_time)+1).'-'.min($count,(($a+1)*$results_at_a_time));
				} else if ($totalPages > 1)	{
					if ($wrapper['browseTextWrap'])	{
						if ($pointer == $a) { // current page
							$pageText = $this->cObj->wrap(($a+1),$wrapper['activeBrowseTextWrap']);
						} else {
							$pageText = $this->cObj->wrap(($a+1),$wrapper['browseTextWrap']);
						}
					} else {
						$pageText = trim($this->pi_getLL('pi_list_browseresults_page','Page',$hscText)).' '.($a+1);
					}
				}
				if ($pointer == $a) { // current page
					if ($this->internal['dontLinkActivePage']) {
						$links[] = $this->cObj->wrap($pageText,$wrapper['activeLinkWrap']);
					} else {
						$linkArray = array($pointerName  => ($a?$a:''));
						$link = $this->pi_linkTP_keepPIvars($pageText,$linkArray,$pi_isOnlyFields);
						$links[] = $this->cObj->wrap($link,$wrapper['activeLinkWrap']);
					}
				} else {
					$links[] = $this->cObj->wrap($this->pi_linkTP_keepPIvars($pageText,array($pointerName => ($a?$a:'')),$pi_isOnlyFields),$wrapper['inactiveLinkWrap']);
				}
			}
			if ($pointer<$totalPages-1 || $showFirstLast)	{
				$nextText = $this->pi_getLL('pi_list_browseresults_next','Next >',$hscText);
				if ($pointer==$totalPages-1) { // Link to next page
					$links[]=$this->cObj->wrap($nextText,$wrapper['disabledLinkWrap']);
				} else {
					$links[]=$this->cObj->wrap($this->pi_linkTP_keepPIvars($nextText,array($pointerName => $pointer+1),$pi_isOnlyFields),$wrapper['inactiveLinkWrap']);
				}
			}
			if ($showFirstLast) { // Link to last page
				if ($pointer<$totalPages-1) {
					$links[]=$this->cObj->wrap($this->pi_linkTP_keepPIvars($this->pi_getLL('pi_list_browseresults_last','Last >>',$hscText),array($pointerName => $totalPages-1),$pi_isOnlyFields),$wrapper['inactiveLinkWrap']);
				} else {
					$links[]=$this->cObj->wrap($this->pi_getLL('pi_list_browseresults_last','Last >>',$hscText),$wrapper['disabledLinkWrap']);
				}
			}
			$theLinks = $this->cObj->wrap(implode(chr(10),$links),$wrapper['browseLinksWrap']);
		} else {
			$theLinks = '';
		}

		$pR1 = $pointer*$results_at_a_time+1;
		$pR2 = $pointer*$results_at_a_time+$results_at_a_time;

		if ($showResultCount) {
			if (isset($wrapper['showResultsNumbersWrap'])) {
				// this will render the resultcount in a more flexible way using markers (new in TYPO3 3.8.0).
				// the formatting string is expected to hold template markers (see function header). Example: 'Displaying results ###FROM### to ###TO### out of ###OUT_OF###'

				$markerArray['###FROM###'] = $this->cObj->wrap($this->internal['res_count'] > 0 ? $pR1 : 0,$wrapper['showResultsNumbersWrap']);
				$markerArray['###TO###'] = $this->cObj->wrap(min($this->internal['res_count'],$pR2),$wrapper['showResultsNumbersWrap']);
				$markerArray['###OUT_OF###'] = $this->cObj->wrap($this->internal['res_count'],$wrapper['showResultsNumbersWrap']);
				$markerArray['###FROM_TO###'] = $this->cObj->wrap(($this->internal['res_count'] > 0 ? $pR1 : 0).' '.$this->pi_getLL('pi_list_browseresults_to','to').' '.min($this->internal['res_count'],$pR2),$wrapper['showResultsNumbersWrap']);
				$markerArray['###CURRENT_PAGE###'] = $this->cObj->wrap($pointer+1,$wrapper['showResultsNumbersWrap']);
				$markerArray['###TOTAL_PAGES###'] = $this->cObj->wrap($totalPages,$wrapper['showResultsNumbersWrap']);
				$pi_list_browseresults_displays = $this->pi_getLL('pi_list_browseresults_displays','Displaying results ###FROM### to ###TO### out of ###OUT_OF###');
				// substitute markers
				$resultCountMsg = $this->cObj->substituteMarkerArray($pi_list_browseresults_displays,$markerArray);
			} else {
				// render the resultcount in the "traditional" way using sprintf
				$resultCountMsg = sprintf(
					str_replace('###SPAN_BEGIN###','<span'.$this->pi_classParam('browsebox-strong').'>',$this->pi_getLL('pi_list_browseresults_displays','Displaying results ###SPAN_BEGIN###%s to %s</span> out of ###SPAN_BEGIN###%s</span>')),
					$count > 0 ? $pR1 : 0,
					min($count,$pR2),
					$count);
			}
			$resultCountMsg = $this->cObj->wrap($resultCountMsg,$wrapper['showResultsWrap']);
		} else {
			$resultCountMsg = '';
		}

		$sTables = $this->cObj->wrap($resultCountMsg.$theLinks,$wrapper['browseBoxWrap']);

		return $sTables;
	}


}


?>
