build_dir . "/$name"); } function config_map_base_dir( array $base_dirs, string $file, bool $normalized = false, bool $strict = true ) : ?string { if(!$normalized) $file = normalize_path($file); foreach($base_dirs as $dir) if(strpos($file, $dir) === 0) return $dir; if($strict) throw new Exception("File '$file' is not mapped to any base dir"); return null; } function config_real_path(array $base_dirs, string $rel_path, bool $strict = true) : ?string { foreach($base_dirs as $dir) if(is_file($dir . '/' . $rel_path)) return $dir . '/' . $rel_path; if($strict) throw new Exception("No file for relative path '$rel_path'"); return null; } function config_is_file(string $filename) : bool { return (strrpos($filename, '.conf.js') === (strlen($filename) - 8)); } function config_file2id(string $conf_dir, string $filename) : int { $nfilename = config_make_path($conf_dir, $filename); return config_crc28($nfilename); } function config_file2strid(string $conf_dir, string $filename) : string { $strid = config_make_path($conf_dir, $filename); $fname_idx = strrpos($strid, "/"); $fname_idx = strpos($strid, ".", $fname_idx); $strid = substr($strid, 0, $fname_idx); return "@".$strid; } function config_make_path(string $conf_dir, string $path) : string { return ltrim(str_replace(normalize_path($conf_dir, true/*nix*/), '', normalize_path($path, true/*nix*/)), '/'); } function config_crc28(string $what) : int { return crc32($what) & 0xFFFFFFF; } function config_get_module_includes(\JSM_Module $cm) : array { $includes = array(); foreach($cm->getIncludes() as $include => $_) { //maybe we should take .php includes into account as well? if(str_ends_with($include, ".php")) continue; $includes[] = $include; } return $includes; } function config_walk_fields(object $proto, callable $callback) { if(!method_exists($proto, 'CLASS_FIELDS_PROPS')) return; foreach($proto->CLASS_FIELDS_PROPS() as $field => $tokens) { $value = $proto->$field; $callback($proto, $field, $value, $tokens); if(is_object($value)) config_walk_fields($value, $callback); else if(is_array($value)) { foreach($value as $num => $item) { if(is_object($item)) config_walk_fields($item, $callback); } } } } function config_includes_map_find_text_origin(array $map, string $file, string $text) : array { if(!isset($map[$file])) return array($file); $tpls = $map[$file]; $tpls[] = $file; $res = array(); foreach($tpls as $tpl) { $content = ensure_read($tpl); $content = i18n_decode_string($content); if(strpos($content, $text) !== FALSE) $res[] = $tpl; } return $res; } function config2json(object $conf, int $json_flags = 0) : string { $arr = $conf->export(true); $arr['class'] = get_class($conf); unset($arr['id']); // @phpstan-ignore-line unset($arr['strid']); // @phpstan-ignore-line $json = json_encode($arr, $json_flags); $json = str_replace(array('\\\\', '\\n', '\/'), array('\\', "\n", '/'), $json); return $json; }