file = $file; try { // @todo Load in the proper attribute objects and objectclass objects // @todo Make sure we have a structural objectclass, or make the template invalid $this->template = json_decode($td->get($file),null,512,JSON_OBJECT_AS_ARRAY|JSON_THROW_ON_ERROR); } catch (\JsonException $e) { $this->invalid = TRUE; $this->reason = $e->getMessage(); } } public function __get(string $key): mixed { return match ($key) { 'attributes' => collect(Arr::get($this->template,$key))->keys(), 'enabled' => Arr::get($this->template,$key,FALSE) && (! $this->invalid), 'icon','regexp','title' => Arr::get($this->template,$key), 'name' => Str::replaceEnd('.json','',$this->file), 'objectclasses' => collect(Arr::get($this->template,$key)), 'order' => collect(Arr::get($this->template,'attributes'))->map(fn($item)=>$item['order']), default => throw new \Exception('Unknown key: '.$key), }; } public function __isset(string $key): bool { return array_key_exists($key,$this->template); } private function autofill() { /* autoFill:string string is a literal string, and may contain many fields like %attr|start-end/flags|additionalcontrolchar% to substitute values read from other fields. |start-end is optional, but must be present if the k flag is used. /flags is optional. |additionalcontrolchar is optional. flags may be: T: Read display text from selection item (drop-down list), otherwise, read the value of the field For fields that aren't selection items, /T shouldn't be used, and the field value will always be read. k: Tokenize: If the "k" flag is not given: A |start-end instruction will perform a sub-string operation upon the value of the attr, passing character positions start-end through. start can be 0 for first character, or any other integer. end can be 0 for last character, or any other integer for a specific position. If the "k" flag is given: The string read will be split into fields, using : as a delimiter "start" indicates which field number to pass through. K: The string read will be split into fields, using ' ' as a delimiter "start" indicates which field number to pass through. If additionalcontrolchar is given, it will be used as delimiter (e.g. this allows for splitting e-mail addresses into domain and domain-local part). l: Make the result lower case. U: Make the result upper case. A: Remap special characters to their corresponding ASCII value */ if (! preg_match('/;/',$arg)) { system_message(array( 'title'=>_('Problem with autoFill() in template'), 'body'=>sprintf('%s (%s)',_('There is only 1 argument, when there should be two'),$attribute->getName(false)), 'type'=>'warn')); return; } list($attr,$string) = preg_split('(([^,]+);(.*))',$arg,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); preg_match_all('/%(\w+)(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U',$string,$matchall); //print"
";print_r($matchall); //0 = highlevel match, 1 = attr, 2 = subst, 3 = mod, 4 = delimiter

				if (! isset($attribute->js['autoFill']))
					$attribute->js['autoFill'] = '';

				$formula = $string;
				$formula = preg_replace('/^([^%])/','\'$1',$formula);
				$formula = preg_replace('/([^%])$/','$1\'',$formula);

				# Check that our attributes match our schema attributes.
				foreach ($matchall[1] as $index => $checkattr) {
					$sattr = $this->getServer()->getSchemaAttribute($checkattr);

					# If the attribute is the same as in the XML file, then dont need to do anything.
					if (! $sattr || ! strcasecmp($sattr->getName(),$checkattr))
						continue;

					$formula = preg_replace("/$checkattr/",$sattr->getName(),$formula);
					$matchall[1][$index] = $sattr->getName();
				}

				$elem_id = 0;

				foreach ($matchall[0] as $index => $null) {
					$match_attr = strtolower($matchall[1][$index]);
					$match_subst = $matchall[2][$index];
					$match_mod = $matchall[3][$index];
					$match_delim = $matchall[4][$index];

					$substrarray = array();

					if (! isset($varcount[$match_attr]))
						$varcount[$match_attr] = 0;
					else
						$varcount[$match_attr]++;

					$js_match_attr = $match_attr;
					$match_attr = $js_match_attr.'xx'.$varcount[$match_attr];

					$formula = preg_replace('/%'.$js_match_attr.'([|\/%])/i','%'.$match_attr.'$1',$formula,1);

					$attribute->js['autoFill'] .= sprintf("  var %s;\n",$match_attr);
					$attribute->js['autoFill'] .= sprintf(
						"  var elem$elem_id = document.getElementById(pre+'%s'+suf);\n".
						"  if (!elem$elem_id) return;\n", $js_match_attr);

					if (strstr($match_mod,'T')) {
						$attribute->js['autoFill'] .= sprintf("  %s = elem$elem_id.options[elem$elem_id.selectedIndex].text;\n",
							$match_attr);
					} else {
						$attribute->js['autoFill'] .= sprintf("  %s = elem$elem_id.value;\n",$match_attr);
					}

					$elem_id++;

					if (strstr($match_mod,'k')) {
						preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
						if (isset($substrarray[1][0])) {
							$tok_idx = $substrarray[1][0];
						} else {
							$tok_idx = '0';
						}
						$attribute->js['autoFill'] .= sprintf("   %s = %s.split(':')[%s];\n",$match_attr,$match_attr,$tok_idx);

					} elseif (strstr($match_mod,'K')) {
						preg_match_all('/([0-9]+)/',trim($match_subst),$substrarray);
						if (isset($substrarray[1][0])) {
							$tok_idx = $substrarray[1][0];
						} else {
							$tok_idx = '0';
						}

						if ($match_delim == '') {
							$delimiter = ' ';
						} else {
							$delimiter = preg_quote($match_delim);
						}
						$attribute->js['autoFill'] .= sprintf("   %s = %s.split('%s')[%s];\n",$match_attr,$match_attr,$delimiter,$tok_idx);

					} else {
						preg_match_all('/([0-9]*)-([0-9]*)/',trim($match_subst),$substrarray);
						if ((isset($substrarray[1][0]) && $substrarray[1][0]) || (isset($substrarray[2][0]) && $substrarray[2][0])) {
							$attribute->js['autoFill'] .= sprintf("   %s = %s.substr(%s,%s);\n",
								$match_attr,$match_attr,
								$substrarray[1][0] ? $substrarray[1][0] : '0',
								$substrarray[2][0] ? $substrarray[2][0] : sprintf('%s.length',$match_attr));
						}
					}

					if (strstr($match_mod,'l')) {
						$attribute->js['autoFill'] .= sprintf("   %s = %s.toLowerCase();\n",$match_attr,$match_attr);
					}
					if (strstr($match_mod,'U')) {
						$attribute->js['autoFill'] .= sprintf("   %s = %s.toUpperCase();\n",$match_attr,$match_attr);
					}
					if (strstr($match_mod,'A')) {
						$attribute->js['autoFill'] .= sprintf("   %s = toAscii(%s);\n",$match_attr,$match_attr);
					}

					# Matchfor only entry without modifiers.
					$formula = preg_replace('/^%('.$match_attr.')%$/U','$1 + \'\'',$formula);
					# Matchfor only entry with modifiers.
					$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%$/U','$1 + \'\'',$formula);
					# Matchfor begining entry.
					$formula = preg_replace('/^%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U','$1 + \'',$formula);
					# Matchfor ending entry.
					$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%$/U','\' + $1 ',$formula);
					# Match for entries not at begin/end.
					$formula = preg_replace('/%('.$match_attr.')(\|[0-9]*-[0-9]*)?(\/[KklTUA]+)?(?:\|(.))?%/U','\' + $1 + \'',$formula);
					$attribute->js['autoFill'] .= "\n";
				}

				$attribute->js['autoFill'] .= sprintf(" fillRec(pre+'%s'+suf, %s); // %s\n",strtolower($attr),$formula,$string);
				$attribute->js['autoFill'] .= "\n";
	}
}