AddJSFile("include/mupload.js");
}
/**
* addCSSFiles
* Add control CSS files to page object
*/
function addCSSFiles()
{
//example
// $this->AddCSSFile("include/mupload.css");
}
/**
* The container's AddCSSFile method wrapper
* @param {String}
*/
function AddCSSFile($fileName)
{
$this->getContainer()->AddCSSFile($fileName);
}
/**
* The container's AddJSFile method wrapper
* @param {String}
*/
function AddJSFile($fileName, $req1="", $req2="", $req3="")
{
$this->getContainer()->AddJSFile($fileName, $req1, $req2, $req3);
}
function getContainer()
{
if(!is_null($this->pageObject))
return $this->pageObject;
else
return $this->container;
}
public function ViewControl($field, $container, $pageObject = null)
{
$this->useUTF8 = "utf-8" == "utf-8";
$this->field = $field;
$this->container = $container;
$this->pageObject = $pageObject;
$this->is508 = isEnableSection508();
$this->fieldType = $container->pSet->getFieldType($this->field);
$this->viewFormat = $container->pSet->getViewFormat($this->field);
$this->editFormat = $container->pSet->getEditFormat($this->field);
if( $this->pageObject )
{
$this->searchClauseObj = $this->pageObject->searchClauseObj;
if ( $this->searchClauseObj )
$this->searchHighlight = $container->searchHighlight && $this->searchClauseObj->bIsUsedSrch;
}
}
/**
* Get the field's content that will be exported
* @prarm &Array data
* @prarm String keylink
* @return String
*/
public function getExportValue(&$data, $keylink = "")
{
return $this->showDBValue($data, $keylink);
}
/**
* Get the field's content
* @prarm &Array data
* @prarm String keylink
* @return String
*/
public function showDBValue(&$data, $keylink = "")
{
$value = $data[$this->field];
if(IsBinaryType($this->fieldType))
{
$value = mlang_message("LONG_BINARY");
$this->searchHighlight = false;
}
if($value === false)
$value = "";
if($this->editFormat == EDIT_FORMAT_CHECKBOX && $this->viewFormat == FORMAT_NONE)
{
if($value && $value!=0)
$value = mlang_message("YES");
else
$value = mlang_message("NO");
$this->searchHighlight = false;
}
if($this->container->forExport == "excel" || $this->container->forExport == "csv")
{
return $value;
}
$processedText = $this->processText($value, $keylink);
return nl2br( $processedText );
}
/**
* Format the text trunceting it or highlighting the search word within this text.
* @param String value The field's content
* @param String keylink
* @return String
*/
public function processText($value, $keylink)
{
$isLookup = false;
$isMobileLookup = false;
$inlineOrFlyMode = false;
if( !is_null($this->pageObject) )
{
$mode = $this->pageObject->mode;
$isLookup = $mode == LIST_LOOKUP;
$isMobileLookup = $isLookup && isMobile();
$inlineOrFlyMode = $mode == EDIT_INLINE || $mode == EDIT_POPUP || $mode == ADD_INLINE || $mode == ADD_POPUP;
}
$isDetailPreview = $this->container->isDetailsPreview;
$pageType = $this->container->pageType;
if( $pageType == PAGE_ADD || $pageType == PAGE_EDIT )
$pageType = PAGE_VIEW;
$isPagePrint = ($pageType == PAGE_RPRINT && $this->container->forExport) || $pageType == PAGE_PRINT || $pageType == PAGE_RPRINT;
if( $this->editFormat == EDIT_FORMAT_LOOKUP_WIZARD )
{
$this->isFieldLookup = true;
$this->needLookupValueProcessing = $this->checkIfLookupValueIsToProcess();
$value = $this->processMultiselectLWValue($value);
}
$cNumberOfChars = $this->container->pSet->getNumberOfChars();
$needShortening = $this->textNeedsTruncating($value, $cNumberOfChars);
if( $needShortening && ($pageType == PAGE_LIST || $pageType == PAGE_REPORT || $inlineOrFlyMode) && !$isMobileLookup && !$isDetailPreview && $keylink != "")
return $this->getShorteningTextAndMoreLink($value, $cNumberOfChars, $keylink, $isLookup);
if( $needShortening && ($isPagePrint || $isMobileLookup || $isDetailPreview) )
return $this->getShorteningText($value, $cNumberOfChars);
return $this->getText($value);
}
/**
* Check if the text needs truncating
* @param String value The field's content
* @param Number cNumberOfChars The number of chars from the 'value' string that will be visible after truncation
* @return Boolean
*/
protected function textNeedsTruncating($value, $cNumberOfChars)
{
return !$this->isUsedForFilter && !$this->container->fullText && $cNumberOfChars > 0 && runner_strlen($value) > $cNumberOfChars;
}
/**
* The object's wrapper for GetShorteningForLargeText function
* @param String value The field's content
* @param Number cNumberOfChars The number of chars up to truncation
* @return String
*/
protected function getShorteningText($value, $cNumberOfChars)
{
return GetShorteningForLargeText($value, $cNumberOfChars)." ...";
}
/**
* Get the More link following the truncated and highlighted field's content
* @param String value The field's content
* @param Number cNumberOfChars The number of chars from the 'value' string that will be visible after truncation
* @param String keylink
* @param Boolean isLookup An indicator showing if this is a lookup list page control
* @return String
*/
protected function getShorteningTextAndMoreLink($value, $cNumberOfChars, $keylink, $isLookup)
{
global $strTableName;
$truncatedValue = GetShorteningForLargeText($value, $cNumberOfChars);
if( $this->searchHighlight )
$truncatedValue = $this->highlightTruncatedBeforeMore($value, $truncatedValue, $cNumberOfChars, $cNumberOfChars);
$params = 'pagetype='.$this->container->pSet->_viewPage.'&table='.GetTableURL($strTableName).'&field='.rawurlencode($this->field).$keylink;
if( $isLookup )
{
$lookupParams = '&maintable='.$this->pageObject->mainTable.'&mainfield='.$this->pageObject->mainField;
$params.= $lookupParams;
}
return $truncatedValue.' '.mlang_message("MORE").' ...';
}
/**
* Get the encoded and highlighted text
* @param String value
* @return String
*/
protected function getText($value)
{
$value = runner_htmlspecialchars($value);
if( $this->searchHighlight )
$value = $this->highlightSearchWord($value, true, "");
return $value;
}
/**
* Check if the fiedl is the project or database table's
* multiselect lookup wizard with the same link and display field
*/
protected function checkIfLookupValueIsToProcess()
{
$pSet = $this->container->pSet;
if( ($pSet->getLookupType($this->field) == LT_LOOKUPTABLE || $pSet->getLookupType($this->field) == LT_QUERY) &&
$pSet->getLWLinkField($this->field) == $pSet->getLWDisplayField($this->field) && $pSet->multiSelect($this->field) )
{
return true;
}
return false;
}
/**
* Remove excessive quotes for the multiselect lookup wizard field with
* the same display and link field
* @param string value
* @return string
*/
protected function processMultiselectLWValue($value)
{
if( !$this->needLookupValueProcessing )
return $value;
return implode(",", splitvalues($value));
}
/**
* Highlight the search word within the $value string
* @param String value The field's content
* @param Boolean encoded An indicator showing if the field's content is htmlspecialchars encoded
* @param String dbValue The database field's value
* @return string
*/
public function highlightSearchWord($value, $encoded, $dbValue = "")
{
if( $dbValue == "" )
{
$dbValue = $value;
}
$lookupParams = $this->getLookupParams();
$highlightData = $this->searchClauseObj->getSearchHighlightingData($this->field, $dbValue, $encoded, $lookupParams);
if( !$highlightData )
{
return $value;
}
return $this->getValueHighlighted($value, $highlightData);
}
/**
* Form the the string with the search word highlighted
* @param String value The field's content
* @param Array highlightData
* @return string
*/
public function getValueHighlighted($value, $highlightData)
{
$searchOpt = $highlightData['searchOpt'];
$searchWordsPattern = $this->getSearchWordPattern($highlightData['searchWords'], false);
switch($searchOpt)
{
case 'Equals':
return $this->addHighlightingSpan($value);
case 'Starts with':
return preg_replace('/(^'.$searchWordsPattern.')/i', $this->addHighlightingSpan('$1'), $value);
case 'Contains':
$pattern = '/('.$searchWordsPattern.')/i';
if( !$this->haveTheSameSpChReference($pattern, $value) )
return preg_replace($pattern, $this->addHighlightingSpan('$1'), $value);
return $this->highlightValueWithSpecialChars($value, $pattern);
default:
return $value;
}
}
/**
* Check if the pattern string is contained in any special chars codes
* occuring in the value string.
* @param string pattern
* @param string value
* @return array
*/
protected function haveTheSameSpChReference($pattern, $value)
{
$scContainedPattern = $this->getSpecialCharsContainingPattern($pattern);
$scFromValue = $this->getSpecialCharsFromString($value);
foreach($scContainedPattern as $sc)
{
if( array_search($sc, $scFromValue) !== FALSE )
return true;
}
return false;
}
/**
* Get the array of special chars contained the pattern
* @param string pattern
* @return array
*/
protected function getSpecialCharsContainingPattern($pattern)
{
$chars = array('&', '"', '<', '>');
$csArray = array();
foreach($chars as $char)
{
if( preg_match($pattern, $char, $matches) )
{
if( $matches[0] != $char )
$csArray[] = $char;
}
}
return $csArray;
}
/**
* Get the array of special chars extracted from the string passed
* @param string str
* @return array
*/
protected function getSpecialCharsFromString($str)
{
$chars = array('&', '"', '<', '>');
$csArray = array();
foreach($chars as $char)
{
if( strpos($str, $char) !== FALSE )
$csArray[] = $char;
}
return $csArray;
}
/**
* Split the string into array that contains all the string's not overlaping
* fragments that are delimeter-substrings and all non-delimeter parts
* adjacent with delimiter-substrings. These fragments are indexed in the
* same order as they occur in the string.
* @param String pattern The regular expression setting delimeter strings
* @param String str The string that is split based on its delimiter-substrings occurrences
* @return Array
*/
protected function getSplitStringWithCapturedDelimiters($pattern, $str)
{
$resArray = array();
if( !strlen($str) )
return $resArray ;
if( !preg_match_all($pattern, $str, $matches) )
{
$resArray[] = $str;
return $resArray;
}
$delimiters = $matches[0];
$strArray = preg_split($pattern, $str);
foreach($strArray as $key=>$item)
{
$resArray[] = $item;
if( isset( $delimiters[$key] ) )
$resArray[] = $delimiters[$key];
}
return $resArray;
}
/**
* Highlight the value escaping the special chars codes
* @param string pattern
* @param string value
* @return string
*/
protected function highlightValueWithSpecialChars($value, $pattern)
{
$chars = array('&', '"', '<', '>');
foreach($chars as $char)
{
$valueArr = $this->getSplitStringWithCapturedDelimiters('/'.$char.'/', $value);
if( count($valueArr) == 1 || !preg_match($pattern, $char, $matches) )
continue;
$valueArr2 = array();
foreach($valueArr as $key=>$part)
{
if( $part != $char )
$valueArr2[] = preg_replace($pattern, $this->addHighlightingSpan('$1'), $part);
else
$valueArr2[] = $char;
}
$value = implode("",$valueArr2);
}
return $value;
}
/**
* Check if the item string has HTML entities
* @param String item
* @return Boolean
*/
protected function hasHTMLEntities($item)
{
if( preg_match_all("/&[^&;]{3,7};/", $item, $matches) )
{
foreach($matches[0] as $entity)
{
$data = getHTMLEntityData($entity);
if( $data['isHTMLEntity'] )
return true;
}
}
return false;
}
/**
* Highlight item string basing on the pattern value
* skipping the HTML entities
* @param String item
* @param String pattern
* @return String
*/
protected function highlightValueWithHTMLEntities($item, $pattern)
{
$valueArr = $this->getSplitStringWithCapturedDelimiters("/&[^&;]{3,7};/", $item);
$valueArr2 = array();
foreach($valueArr as $subitem)
{
$data = getHTMLEntityData($subitem);
if( $data['isHTMLEntity'] )
$valueArr2[] = $subitem;
else
$valueArr2[] = preg_replace($pattern, $this->addHighlightingSpan('$1'), $subitem);
}
return implode("",$valueArr2);
}
/**
* Get the lookup params and settings to pass it
* to the searchClause object's getSearchHighlightingData method
* @return Array
*/
protected function getLookupParams()
{
$lookupParams = array();
if( $this->isFieldLookup )
{
$pSet = $this->container->pSet;
$lookupParams["multiselect"] = $pSet->multiSelect($this->field);
$lookupParams["needLookupProcessing"] = $this->needLookupValueProcessing;
//linkFieldValue and originLinkValue params are set for looku fields with distinct Link and Displayed fields only
$lookupParams["linkFieldValue"] = $this->container->linkFieldValues[$this->field];
//originLinkValue param is set for multiselet lookups only
$lookupParams["originLinkValue"] = $this->container->originlinkValues[$this->field];
}
return $lookupParams;
}
/**
* Get the first search word from the text truncating field's value
* @param Array searchWords
* @param String value The raw field's value
* @return String
*/
protected function getFirstSearchWordInLargeText($searchWords, $value)
{
$searchWordsPattern = $this->getSearchWordPattern($searchWords, false);
if( preg_match('/'.$searchWordsPattern.'/i', $value, $matches) )
return $matches[0];
return $searchWords[0];
}
/**
* Format the string before the "More ..." link and highlight a search word depending on the search option's value.
* @param String value The raw field's content
* @param String truncatedValue The truncated, htmlspecialchars encoded field's content
* @param Number cNumberOfChars
* @prarm Number contenLength The length of the truncated value
* @return string
*/
protected function highlightTruncatedBeforeMore($value, $truncatedValue, $cNumberOfChars, $contenLength)
{
$lookupParams = $this->getLookupParams();
$highlightData = $this->searchClauseObj->getSearchHighlightingData($this->field, $value, false, $lookupParams);
if(!$highlightData)
{
return $truncatedValue;
}
$searchWord = $this->getFirstSearchWordInLargeText($highlightData['searchWords'], $value);
$searchWordEncoded = runner_htmlspecialchars($searchWord);
$highlighting = $this->addHighlightingSpan($searchWordEncoded);
$searchOpt = $highlightData['searchOpt'];
switch ($searchOpt)
{
case 'Equals':
return $this->addHighlightingSpan($truncatedValue);
case 'Starts with':
if( strlen($searchWordEncoded) > strlen($truncatedValue) )
return $this->addHighlightingSpan($truncatedValue);
return preg_replace('/^'.preg_quote($searchWordEncoded,"/").'/i', $highlighting, $truncatedValue);
case 'Contains':
$regExpModifier = $this->useUTF8 ? 'u' : '';
$firstPos = $this->getFistOccurencePosition($value, $searchWord, $searchWordEncoded);
$lastPos = $this->getLastOccurencePosition($value, $searchWord, $searchWordEncoded);
$searchWordEncodedLen = runner_strlen($searchWordEncoded);
$truncLen = runner_strlen($truncatedValue);
$pattern = '/('.$this->getSearchWordPattern($highlightData['searchWords'], true).')/i';
if( $lastPos + $searchWordEncodedLen <= $truncLen || $firstPos + $searchWordEncodedLen <= $truncLen )
{
if( !$this->haveTheSameSpChReference($pattern, $truncatedValue) )
return preg_replace($pattern.$regExpModifier, $this->addHighlightingSpan('$1'), $truncatedValue);
return $this->highlightValueWithSpecialChars($truncatedValue, $pattern.$regExpModifier);
}
if( $firstPos > $truncLen )
{
$newNumberOfChars = ceil($cNumberOfChars / 2);
$qNumberOfChars = ceil($cNumberOfChars / 4);
$firstPosDecoded = runner_strpos($value, $searchWord);
$truncSubsr = runner_substr($value, 0, $cNumberOfChars);
$valueSubstr = runner_substr($value, $firstPosDecoded - $qNumberOfChars, $qNumberOfChars + runner_strlen($searchWord));
$truncSubsr = runner_substr($truncSubsr, 0, $newNumberOfChars);
$valueSubstr = runner_htmlspecialchars($valueSubstr);
$pattern = '/('.preg_quote($searchWordEncoded,"/").')/i';
if( !$this->haveTheSameSpChReference($pattern, $valueSubstr) )
$valueSubstr = preg_replace($pattern.$regExpModifier, $highlighting, $valueSubstr);
else
$valueSubstr = $this->highlightValueWithSpecialChars($valueSubstr, $pattern.$regExpModifier);
return runner_htmlspecialchars($truncSubsr)." <...> ".$valueSubstr;;
}
return runner_substr($truncatedValue, 0, $firstPos).$highlighting;
default:
return $truncatedValue;
}
}
/**
* Get the first searchWord occurence in the encoded value string
* @param String value
* @param String searchWord
* @param String searchWordEncoded
* @return Number
*/
protected function getFistOccurencePosition($value, $searchWord, $searchWordEncoded)
{
$planeFirstPos = strpos($value, $searchWord);
$planeSubstr = substr($value, 0, $planeFirstPos);
$encodedPlaneSubstr = runner_htmlspecialchars($planeSubstr);
return runner_strpos( runner_htmlspecialchars($value), $searchWordEncoded, runner_strlen($encodedPlaneSubstr) );
}
/**
* Get the last searchWord occurence in the encoded value string
* @param String value
* @param String searchWord
* @param String searchWordEncoded
* @return Number
*/
protected function getLastOccurencePosition($value, $searchWord, $searchWordEncoded)
{
$planeLastPos = strrpos($value, $searchWord);
$planeSubstr = substr($value, 0, $planeLastPos);
$encodedPlaneSubstr = runner_htmlspecialchars($planeSubstr);
return runner_strrpos(runner_htmlspecialchars($value), $searchWordEncoded, runner_strlen($encodedPlaneSubstr));
}
/**
* Get common search words pattern
* @param Array searchWords
* @param Boolean encoded
* @return String
*/
protected function getSearchWordPattern($searchWords, $encoded = false)
{
$searchWordsPatterns = array();
foreach($searchWords as $searchWord)
{
$wordPattern = preg_quote($searchWord, "/");
if( $encoded )
$wordPattern = runner_htmlspecialchars($wordPattern);
$searchWordsPatterns[] = $wordPattern;
}
return implode('|', $searchWordsPatterns);
}
/**
* Wrap the string value with a span element
* @param String str
* @return String
*/
public function addHighlightingSpan($str)
{
return ''.$str.'';
}
public function & getJSControl()
{
if(!isset($this->getContainer()->viewControlsMap["controls"]))
$this->getContainer()->viewControlsMap["controls"] = array();
for($i = 0; $i < count($this->getContainer()->viewControlsMap["controls"]); $i++)
if($this->getContainer()->viewControlsMap["controls"][$i]["fieldName"] == $this->field)
return $this->getContainer()->viewControlsMap["controls"][$i];
$this->getContainer()->viewControlsMap["controls"][$i] = array("fieldName" => $this->field, "viewFormat" => $this->viewFormat);
return $this->getContainer()->viewControlsMap["controls"][count($this->getContainer()->viewControlsMap["controls"]) - 1];
}
/**
* addJSControlSetting
* Add setting for JS control to controls map
* @param {string} setting name
* @param {object} setting value
*/
public function addJSControlSetting($name, $value)
{
$JScontrol =& $this->getJSControl();
$JScontrol[$name] = $value;
}
/**
* Check for need to load the javascript files
* @return boolean
*/
public function neededLoadJSFiles()
{
switch ($this->getContainer()->pageType)
{
case PAGE_PRINT:
return false;
default:
return true;
}
}
/**
* Returns true if it is user control
* @return boolean
*/
public function isUserControl()
{
return $this->userControl && $this->userControl === true;
}
/**
* Returns css code for thumbnail size optionally wrapped into style="" attribute
*/
protected function getThumbnailSizeStyle($returnStyleAttr = true)
{
$width = $this->container->pSet->getThumbnailSize($this->field);
if(!$width)
return "";
$style = 'max-width:'.$width.'px; max-height:'.$width.'px;';
if( $returnStyleAttr )
return ' style="'.$style.'"';
return $style;
}
/**
* Returns css code for image size optionally wrapped into style="" attribute
*/
protected function getImageSizeStyle($returnStyleAttr = true)
{
$imgWidth = $this->container->pSet->getImageWidth($this->field);
$imgHeight = $this->container->pSet->getImageHeight($this->field);
if(!$imgWidth && !$imgHeight)
return "";
$style = '';
if( $imgWidth )
$style .= 'max-width:'.$imgWidth.'px;';
if( $imgHeight )
$style .= 'max-height:'.$imgHeight.'px;';
if( $returnStyleAttr )
return ' style="'.$style.'"';
return $style;
}
}
class ViewControlTypes
{
public $viewTypes = array();
function ViewControlTypes()
{
$this->viewTypes[FORMAT_NONE] = "";
$this->viewTypes[FORMAT_DATE_SHORT] = "ViewShortDateField";
$this->viewTypes[FORMAT_DATE_LONG] = "ViewLongDateField";
$this->viewTypes[FORMAT_DATE_TIME] = "ViewDatetimeField";
$this->viewTypes[FORMAT_TIME] = "ViewTimeField";
$this->viewTypes[FORMAT_CURRENCY] = "ViewCurrencyField";
$this->viewTypes[FORMAT_PERCENT] = "ViewPercentField";
$this->viewTypes[FORMAT_HYPERLINK] = "ViewHyperlinkField";
$this->viewTypes[FORMAT_EMAILHYPERLINK] = "ViewEmailHyperlinkField";
$this->viewTypes[FORMAT_DATABASE_IMAGE] = "ViewDatabaseImageField";
$this->viewTypes[FORMAT_DATABASE_FILE] = "ViewDatabaseFileField";
$this->viewTypes[FORMAT_FILE] = "ViewFileDownloadField";
$this->viewTypes[FORMAT_FILE_IMAGE] = "ViewImageDownloadField";
$this->viewTypes[FORMAT_FILE_IMAGE_OLD] = "ViewDocumentDownloadOldField";
$this->viewTypes[FORMAT_PHONE_NUMBER] = "ViewPhoneNumberField";
$this->viewTypes[FORMAT_NUMBER] = "ViewNumberField";
$this->viewTypes[FORMAT_CHECKBOX] = "ViewCheckboxField";
$this->viewTypes[FORMAT_MAP] = "ViewMapField";
$this->viewTypes[FORMAT_AUDIO] = "ViewAudioFileField";
$this->viewTypes[FORMAT_DATABASE_AUDIO] = "ViewDatabaseAudioField";
$this->viewTypes[FORMAT_VIDEO] = "ViewVideoFileField";
$this->viewTypes[FORMAT_DATABASE_VIDEO] = "ViewDatabaseVideoField";
$this->viewTypes[FORMAT_CUSTOM] = "ViewCustomField";
$this->viewTypes[FORMAT_LOOKUP_WIZARD] = "ViewLookupWizardField";
$this->viewTypes[FORMAT_HTML] = "ViewHTMLField";
}
}
?>