CoolFace
Apppublic

kenken999/php

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
context.php623 linesDownload Raw Back to classes
1<?php2class RunnerContextItem3{4/**5 * define('CONTEXT_GLOBAL', 0);	//	global context6 * define('CONTEXT_PAGE', 1);		//	page where pageObject is available7 * define('CONTEXT_BUTTON', 2);	// 	button or other AJAX event8 * define('CONTEXT_LOOKUP', 3);	//	dependent lookup9 * define('CONTEXT_ROW', 4);		// 	processing grid row on multiple-records page (list)10 * define('CONTEXT_COMMAND', 5);	// 	DsCommand context11 * define('CONTEXT_SEARCH', 6);	// 	Search object context12 * define('CONTEXT_MASTER', 7);	// 	Search object context13 */14	public $type; 15 16	public $pageObj;17	public $data;18	public $oldData;19	public $newData;20	public $detailsKeys;21	public $dc;22	public $searchClause;23	public $masterData;24 25	function __construct( $type, $params )26	{27		RunnerApply($this, $params);28		$this->type = $type;29	}30 31	public function getType()32	{33		return $this->type;34	}35 36	/**37	 * @return Array38	 */39	public function getValues()40	{41		if( $this->data )42			return $this->data; 43 44		if( $this->dc ) {45			return $this->dc->values;46		}47	48		if( $this->pageObj )49			return $this->pageObj->getCurrentRecord();50 51		return array();52	}53 54	/**55	 * @param String field56	 * @return Mixed57	 */58	public function getFieldValue( $field )59	{60		$data = $this->getValues();61		return  getArrayElementNC( $data, $field );62	}63 64	public function getSearchValue( $field ) {65		return $this->searchClause->_getFieldValue( $field, null, false, true );66	}67 68	public function getAllSearchValue() {69		return $this->searchClause->getAllFieldsSearchValue();70	}71 72	/**73	 * @return Array74	 */75	public function getOldValues()76	{77		if( $this->oldData )78			return $this->oldData;79 80		if( $this->pageObj )81			return $this->pageObj->getOldRecordData();82 83		return array();84	}85 86	public function getKeyValue( $field ) {87		if( $this->dc ) {88			return $this->dc->keys[ $field ];89		}90		return null;91	}92 93	public function getOrderValue( $key ) {94		if( !$this->dc ) {95			return null;96		}97		$idx = 0;98		if( substr( $key, 0, 5) == "field" ) {99			$param = "field";100			$idx = (int)substr( $key, 5);101		} else if( substr( $key, 0, 3 ) == "dir" ) {102			$param = "dir";103			$idx = (int)substr( $key, 3);104		}105		if( !$idx || $idx < 1 ) {106			return null;107		}108		if( count( $this->dc->order ) <= $idx ) {109			return null;110		}111		$order = $this->dc->order[ $idx - 1 ];112		if( $param == "field") {113			return $order["column"];114		}115		if( $param == "dir") {116			return $order["dir"];117		}118		return null;119	}120 121 122	public function getFilterValue( $field ) {123		if( $this->dc ) {124			return $this->dc->findFieldFilterValue( $field );125		}126	}127 128	public function getLimitValue( $key ) {129		if( !$this->dc ) {130			return "";131		}132		if( $key == "record_from" ) {133			return $this->dc->startRecord + 1;134		}135		if( $key == "record_to" ) {136			return $this->dc->startRecord + $this->dc->reccount;137		}138		if( $key == "record_count" ) {139			return $this->dc->reccount;140		}141		if( $key == "record_offset" ) {142			return $this->dc->startRecord;143		}144	}145 146 147	/**148	 * @param String field149	 * @return Mixed150	 */151	public function getOldFieldValue( $field )152	{153		$oldData = $this->getOldValues();154		return getArrayElementNC( $oldData, $field );155	}156 157	/**158	 * @param String field159	 * @return Mixed160	 */161	public function getNewFieldValue( $field )162	{163		if ( $this->newData )164			return getArrayElementNC( $this->newData, $field );165		if( $this->dc ) {166			return getArrayElementNC( $this->dc->values, $field );167		}168 169		return $this->getFieldValue( $field );170	}171 172	173 174	/**175	 * @return Array176	 */177	public function getMasterValues()178	{179		if( $this->masterData )180			return $this->masterData;181 182		if( $this->pageObj )183			return $this->pageObj->getMasterRecord();184 185		return array();186	}187 188	/**189	 * @param String field190	 * @return Mixed191	 */192	public function getMasterFieldValue( $field )193	{194		$masterData = $this->getMasterValues();195		if( !$masterData ) {196			return "";197		}198		return getArrayElementNC( $masterData, $field );199		200	}201 202	/**203	 * @param String key204	 * @return String205	 */206	public function getUserValue( $key )207	{208		return getArrayElementNC( Security::currentUserData(), $key );209	}210 211	/**212	 * @param String key213	 * @return Mixed214	 */215	public function getSessionValue( $key )216	{217		return getSessionElementNC( $key );218	}219 220	public function getDetailsKeyValue( $key ) {221		return $this->detailsKeys[ $key ];222	}223 224 225	/**226	 * Returns true if context must serve this scope, and search must stop here. 227	 * For example, when page context is found, it must serve the 'master' and 'details' scopes even if no master-detail is in effect.228	 * @param String - scope like 'keys', 'master', 'details'229	 * @return Boolean230	 */231	public function hasScope( $scope ) {232		if( $scope == "master" )233			return $this->masterData || $this->type == CONTEXT_PAGE;234 235		if( $scope == "session" )236			return true;237 238		if( $scope == "user" )239			return true;240 241		if( $scope == "old" )242			return $this->oldData || $this->type == CONTEXT_PAGE;243 244		if( $scope == "keys" )245			return $this->type == CONTEXT_COMMAND;246 247		if( $scope == "order" )248			return $this->type == CONTEXT_COMMAND;249 250 251		if( $scope == "new" )252			return $this->newData || $this->type == CONTEXT_PAGE || $this->type == CONTEXT_COMMAND;253 254		if ( $scope == "global" )255			return true;256 257		if( $scope == "details" )258			return $this->type == CONTEXT_PAGE || $this->type == CONTEXT_MASTER;259 260		if ( $scope == "values" )261			return !!$this->data || $this->type == CONTEXT_PAGE || $this->type == CONTEXT_COMMAND; 262 263		if( $scope == "search" )264			return $this->type == CONTEXT_SEARCH;265 266		if( $scope == "filter" )267			return $this->type == CONTEXT_COMMAND;268 269		if( $scope == "request" )270			return true;271 272		if( $scope == "limit" )273			return $this->type == CONTEXT_COMMAND;274		275		if( $scope == "all_field_search" )276			return $this->type == CONTEXT_SEARCH;277	}278 279	/**280	 * @param String key281	 * @return Mixed282	 */283	public function getContextValue( $scope, $key )284	{285 286		if( $scope == "master" )287			return $this->getMasterFieldValue( $key );288 289		if( $scope == "session" )290			return $this->getSessionValue( $key );291 292		if( $scope == "user" )293			return $this->getUserValue( $key );294 295		if( $scope == "old" )296			return $this->getOldFieldValue( $key );297 298		if( $scope == "keys" )299			return $this->getKeyValue( $key );300 301		if( $scope == "order" )302			return $this->getOrderValue( $key );303 304		if( $scope == "new" )305			return $this->getNewFieldValue( $key );306 307		if ( $scope == "global" && $key == "language" )308			return mlang_getcurrentlang();309 310		if( $scope == "details" ) {311			if( $this->type == CONTEXT_PAGE )312				return $this->pageObj->getDetailsKeyValue( $key );313			if( $this->type == CONTEXT_MASTER )314				return $this->getDetailsKeyValue( $key );315		}316 317		if( $scope == "values" )318			return $this->getFieldValue( $key );319 320		if( $scope == "search" )321			return $this->getSearchValue( $key );322 323		if( $scope == "filter" )324			return $this->getFilterValue( $key );325 326		if( $scope == "request" )327			return postvalue( $key );328 329		if( $scope == "limit" )330			return $this->getLimitValue( $key );331		332		if( $scope == "all_field_search" )333			return $this->getAllSearchValue();334			335		return false;336	}337}338 339/**340 *	Singletone. All public functions are static341 */342class RunnerContext343{344	protected $stack = array();345 346	public function __construct( )347	{348		$context = new RunnerContextItem( CONTEXT_GLOBAL, array() );349		$this->stack[ count($this->stack) ] = $context;350	}351 352	public static function push( $context )353	{354		global $contextStack;355		$contextStack->stack[ count($contextStack->stack) ] = $context;356	}357 358	public static function current( )359	{360		global $contextStack;361		return $contextStack->stack[ count($contextStack->stack) - 1 ];362	}363 364	public static function pop( )365	{366		global $contextStack;367 368		//	this sometimes happens during the error reporting369		if( !$contextStack->stack )370			return null;371		372		$context = $contextStack->stack[ count($contextStack->stack) - 1 ];373		unset( $contextStack->stack[ count($contextStack->stack) - 1 ] );374 375		return $context;376	}377 378	 // Utility functions379	/**380	 *  Shortcut for adding page-based context381	 */382	public static function pushPageContext( $pageObj ) {383		RunnerContext::push( new RunnerContextItem( CONTEXT_PAGE, array( "pageObj" => $pageObj ) ) );384	}385	/**386	 *  Shortcut for adding record-based context387	 */388	public static function pushRecordContext( $record, $pageObj ) {389		RunnerContext::push( new RunnerContextItem( CONTEXT_ROW, array( "pageObj" => $pageObj, "data" => $record ) ) ); //?390	}391 392	public static function pushDataCommandContext( $dc ) {393		RunnerContext::push( new RunnerContextItem( CONTEXT_COMMAND, array( "dc" => $dc ) ) ); 394	}395 396	public static function pushSearchContext( $searchClause ) {397		RunnerContext::push( new RunnerContextItem( CONTEXT_SEARCH, array( "searchClause" => $searchClause ) ) );398	}399 400	public static function pushMasterContext( $detailsKeys ) {401		RunnerContext::push( new RunnerContextItem( 402			CONTEXT_MASTER, 403			array( 404				"detailsKeys" => $detailsKeys, 405			) ) ); 406	}407 408 409	public static function getMasterValues() {410		$ctx = RunnerContext::current();411		return $ctx->getMasterValues();412	}413 414	public static function getValues() {415		$ctx = RunnerContext::current();416		return $ctx->getValues();417	}418 419	/**420	 * @return String421	 */422	public static function PrepareRest( $str, $urlenc = true ) {423		$context = RunnerContext::current();424		$tokens = DB::scanTokenString($str);425 426		$replacements = array();427		// build array of replacements in this format:428		//	"offset" => position in the string where replacement should be done429		//  "len" => length of original substring to cut out430		//  "insert" => string to insert in place of cut out431 432		foreach ($tokens["matches"] as $i => $match) {433			$offset = $tokens["offsets"][$i];434			$token = $tokens["tokens"][$i];435 436			$repl = array(437				"offset" => $offset,438				"len" => strlen($match)439			);440			$val = "";441			if (is_numeric($token) && count( $args ) > $token) {442				$val = $args[(int)$token];443			} else {444				$val = RunnerContext::getValue($token);445			}446			if( $urlenc )447				$val = rawurlencode($val);448			$repl["insert"] = $val;449 450			$replacements[] = $repl;451		}452		//	do replacements453		return RunnerContext::doReplacements( $str, $replacements );454	}455 456	/**457	 * locate all <? - ?> snippets in a string458	 * @param String str459	 * @return Array of array(460	 * 	"offset" => integer - offset of the opening bracket in the original string461	 * 	"len" => integer - length includes opening and closing brackets: <? - ?>462	 * )463	 */464	protected static function getOptionalBlocks( $str ) {465		if( !is_string( $str ) )466			return array();		467		468		$snippetStack = array();469		$snippets = array();470		$pos = strpos( $str, '<?' );471		if( $pos === false )472			return array();473		474		while( true ) {475			$snippetStack[] = $pos;476			$newPos = strpos( $str, '<?', $pos + 1 );477			478			/*	locate all ?> before the next <? or end of string*/479			$tailLen = ( $newPos !== false ? $newPos : strlen( $str ) ) - $pos;480			$tail = substr( $str, $pos, $tailLen );481			$endPos = 0;482			while( ($endPos = strpos( $tail, '?>', $endPos+1 ) ) !== false && count( $snippetStack ) ) {483				$stackIdx = count( $snippetStack ) - 1;484				$snippets[] = array( "offset" => $snippetStack[ $stackIdx ], "len" => $endPos + $pos + 2 - $snippetStack[ $stackIdx ] );485				$snippetStack = array_slice( $snippetStack, 0, $stackIdx );486			}487			if( $newPos === false ) 488				break;489			$pos = $newPos;490		}491		return $snippets;492	}493 494	/**495	 * do actual replacements496	 * @param String $str - source string497	 * @param Array $replacements - Array of Array(498	 * 		"offset" => Integer, position in the source tring499	 * 		"len"	=> Integer, length of the source string portion to be replaced500	 * 		"insert" => String, value to insert instead of replaced501	 * )502	 */503	public static function doReplacements( $str, $replacements ) {504		if( !is_string( $str ) )505			return $str;506		507		$snippets = RunnerContext::getOptionalBlocks( $str );508		/* snippets with 0 non-empty requirements must be deleted from the string */509		/* mark empty snippets */510		for( $i=0; $i < count( $snippets ); ++$i ) {511			$s = &$snippets[$i];512			$s["empty"] = true;513			foreach ($replacements as $r) {514				/* replacement inside snippet  */515				if( $r["offset"] > $s["offset"] && $r["offset"] < $s["offset"] + $s["len"] ) {516					if( $r["insert"] != "" ) {517						$s["empty"] = false;518						break;519					}520				}521			}522		} 523 524		/* do replacements */525		$offsetShift = 0;526		foreach ($replacements as $r) {527			$str = substr_replace($str, $r["insert"], $r["offset"] + $offsetShift, $r["len"]);528			$offsetDelta = strlen($r["insert"]) - $r["len"];529			//	update all $snippets530			RunnerContext::updateOptionalBlockOffset( $snippets, $r["offset"], $offsetDelta );531			$offsetShift += $offsetDelta;532		}533 534		/* process optional blocks - delete or remove brackets */535		for( $i=0; $i < count( $snippets ); ++$i ) {536			$s = &$snippets[$i];537			if( $s["empty"]) {538				$str = substr_replace($str, "", $s["offset"], $s["len"] );539				$offsetDelta = -$s["len"];540			} else {541				$str = substr_replace($str, 542					substr( $str, $s["offset"] + 2, $s["len"] - 4 ), 543					$s["offset"], 544					$s["len"] 545				);546				$offsetDelta = -4;547			}548			RunnerContext::updateOptionalBlockOffset( $snippets, $s["offset"], $offsetDelta );549		}550		return $str;551	}552 553	protected static function updateOptionalBlockOffset( &$snippets, $offset, $delta ) {554		for( $i=0; $i < count( $snippets ); ++$i ) {555			$s = &$snippets[$i];556			if( $s["offset"] > $offset ) {557				$s["offset"] += $delta;558			} else {559				if( $s["offset"] + $s["len"] > $offset ) {560					$s["len"] += $delta;561				}562			}563		}564	}565	566 567	public static function getValue( $key ) {568		$prefix = "";569		$dotPos = strpos( $key, ".");570		if( $dotPos !== FALSE )571		{572			$scope = strtolower( substr( $key, 0, $dotPos ) );573			$key = substr( $key, $dotPos + 1 );574		} else {575			if( $key === "language" ) {576				$scope = "global";577			} else if( $key == "all_field_search") {578				$scope = $key;579			} else {580				$scope = "values";581			}582 583		}584		return RunnerContext::_getValue( $scope, $key );585	}586 587 588	/**589	 * Search got requested value in the stack of contexts590	 * @param String - scope like 'keys', 'master', 'details'591	 * @param String - key. 'details.teamId' is translated to context=details, key=teamId592	 * @return String or false if value is not found593	 */594	protected static function _getValue( $scope, $key ) 595	{596		global $contextStack;597		$idx = count( $contextStack->stack );598		while( $idx > 0 ) {599			$ctx = $contextStack->stack[ --$idx ];600			if( $ctx->hasScope( $scope ) ) {601				return $ctx->getContextValue( $scope, $key );602			}603		}604		return false;605	}606 607}608 609/**610 * 	Push context in constructor and pop in destructor611 */612class TempContext613{614	function __construct( $context ) {615		RunnerContext::push( $context );616	}617 618	function __destruct() {619		RunnerContext::pop();620	}621}622 623?>