taskman_config/parse.inc.php

176 lines
4.4 KiB
PHP
Raw Permalink Normal View History

<?php
namespace taskman;
use Exception;
class ConfigParseResult
{
public int $error = 0;
public string $error_descr;
public string $normalized_jzon = '';
public array $parsed_arr;
public int $parser_type;
public $jsm_module;
}
function config_parse(array $base_dirs, string $file) : ConfigParseResult
{
$res = new ConfigParseResult();
$normalized_jzon = '';
try
{
$jsm = new \JSM($base_dirs, $file);
list($normalized_jzon, $jsm_module) = $jsm->process();
$res->normalized_jzon = $normalized_jzon;
$res->jsm_module = $jsm_module;
}
catch(Exception $e)
{
$res->error = 1;
$res->error_descr = $e->getMessage() . "\n" . $e->getTraceAsString();
return $res;
}
$decode_res = config_check_and_decode_jzon($normalized_jzon);
if($decode_res[0] === 0)
{
$res->parsed_arr = $decode_res[2];
$res->parser_type = $decode_res[3];
}
else
{
$res->error = $decode_res[0];
2025-02-25 20:04:47 +03:00
$res->error_descr = $decode_res[1];
}
return $res;
}
function config_check_and_decode_jzon(string $json) : array
{
try
{
2025-02-25 13:48:24 +03:00
$parser = 0;
$arr = \jzon_parse($json, $parser);
return array(0, "", $arr, $parser);
}
catch(Exception $e)
{
return array(1, $e->getMessage(), array(), 0);
}
}
function config_get_header(string $file, ?int &$conf_id, ?string &$strid, bool $use_cache = true) : bool
{
static $cache = array();
if($use_cache && isset($cache[$file]))
{
list($conf_id, $strid) = $cache[$file];
return true;
}
$h = fopen($file, "r");
$line = fgets($h, 256);
fclose($h);
//TODO: rewrite it without regex usage
if(preg_match('~\{\s*/\*\s*proto_id\s*=\s*(\d+)\s*;\s*alias\s*=\s*([^\s]+)~', $line, $matches))
{
$conf_id = (int)$matches[1];
$strid = $matches[2];
if($use_cache)
$cache[$file] = array($conf_id, $strid);
return true;
}
else
return false;
}
function config_set_header(string $contents, int $conf_id, string $strid, bool &$is_success) : string
{
$contents = preg_replace('~\s*\{~', "{ /* proto_id = {$conf_id} ; alias = {$strid} */", $contents, 1/*limit*/, $count);
$is_success = $count == 1;
return $contents;
}
function config_replace_header(string $contents) : string
{
return preg_replace('~(\s*\{)\s*/\*\s*proto_id\s*=\s*\d+\s*;\s*alias\s*=\s*[^\s]+\s*\*/~', '$1', $contents);
}
//returns [proto_id, alias]
function config_ensure_header(string $conf_dir, string $file, bool $force = false) : array
{
if(config_get_header($file, $curr_proto_id, $curr_alias, !$force))
{
//TODO: add 'normalized' argument when we are sure both path arguments are normalized
$alias = config_file2strid($conf_dir, $file);
if($force)
$curr_proto_id = config_file2id($conf_dir, $file);
//NOTE: keeping current proto id intact if not forced
if($force || $curr_alias !== $alias)
{
$lines = file($file);
//TODO: why not using config_set_header(..) ?
$lines[0] = preg_replace(
'~\s*\{\s*/\*\s*proto_id\s*=\s*\d+\s*;\s*alias\s*=\s*[^\s]+\s*\*/~', "{ /* proto_id = {$curr_proto_id} ; alias = {$alias} */",
$lines[0],
1/*limit*/,
$count);
if($count != 1)
throw new Exception("Could not set header for '$file' in line: {$lines[0]}");
ensure_write_if_differs($file, join("", $lines));
}
return array($curr_proto_id, $alias);
}
else
{
$conf_id = config_file2id($conf_dir, $file);
$alias = config_file2strid($conf_dir, $file);
$lines = file($file);
$is_success = false;
$lines[0] = config_set_header($lines[0], $conf_id, $alias, $is_success);
if(!$is_success)
throw new Exception("Could not set header for '$file' in line: {$lines[0]}");
ensure_write($file, join("", $lines));
return array($conf_id, $alias);
}
}
function config_apply_class_normalization(array $kv_data, bool $check_junk = false) : array
{
$class = $kv_data['class'];
$norm_data = array();
unset($kv_data['class']);
call_user_func_array([$class, 'normalize'],
array(&$kv_data, &$norm_data, true, $check_junk));
return array($class, $class::CLASS_ID, $norm_data);
}
//returns array<ref, number>
function config_content_match_refs(string $src) : array
{
$refs = array();
if(strpos($src, '@') === false)
return $refs;
if(preg_match_all('~"(@[^"]+)"~', $src, $matches))
{
foreach($matches[1] as $ref)
{
if(!isset($refs[$ref]))
$refs[$ref] = 1;
++$refs[$ref];
}
}
return $refs;
}