Improving a rule engine

Posted 3 months ago by oliverbusk

I am trying to create a simple parsing rule engine, that can parse text according to some parsing rules the user can define.

The problem I've encountered is that my users can currently save text into to my database in two ways:

documents:

id | path           | content
1  | /mydoc.txt     | {"text":"My document text.\nIs awesome!\n\f"}
2  | /another.txt   | {"column":[{"1":[{"1":"A line in column 1.\n"}],"2":[{"1":"Another line.\n"},{"2":"Yet another in column 2\n"}]}]}

So my users can parse a text string text: and column / table rows column:

I have created a class, that can parse rules:

ApplyParsingRules.php;

public function parseContent(array $content, Field $field)
{
    if ($field->rules->count() > 0) {
        $result['text'] = $this->parse($content, $field->rules);
        $result = json_encode($result);
    }

    return $this->data->fields()->attach($field, ['content' => $result ?? null]);
}

/**
 * Iterate through each rule and parse through the content.
 *
 * @return array
 */
public function parse(array $content, object $rules) : string
{
    $results = [];

    foreach ($rules as $rule) {
        $class = $this->getClass($rule);
        $content = $class->apply($content);
    }

    return $content;
}
public function getClass(FieldRule $FieldRule)
{
    $arguments = unserialize($FieldRule->arguments);
    $class = 'App\StreamParser\Parser\ParsingRules\Text\' . Str::camel($FieldRule->method);
    return new $class($arguments);
}

And it is called like:

$Parser = new ApplyParsingRules();
$result = $Parser->parseContent($content, $field);

An example rule could be textReplace.php:

public function __construct(array $arguments)
{
    $this->search = $arguments['search'];
    $this->replace = $arguments['replace'];
}

public function apply(array $content): string
{
    return str_replace($this->search, $this->replace, $content['text']);
}

Above setup works fine. I can provide the $content['text'] from the database, which is basically:

My document text.\nIs awesome!\n\f

However, I would like to allow for this to also parse the column data (for example, only perform text replacement in column 2, or capitalize everything in column 1, row 1.

Any tips / ideas on how I can improve my rule class to accept both the $content['text'] and $content['column'][$i] ?

Please sign in or create an account to participate in this conversation.