Generic Conditional Logic Plugin

Plugin source location: <serge_root>/lib/Serge/Engine/Plugin/if.pm

Plugin always attaches itself to the following callback phase: before_job.

Plugin must also be attached through the configuration file to either of the following phases:

This plugin allows to define conditional 'if' / 'if not' logic, and do some action when a condition is satisfied. This is a base plugin that doesn't change the localization behavior or perform any actions on localized files. Several other descendant plugins, namely process_if, replace_strings, and run_command, inherit all the logic of the 'if' plugin and use it to control different callback phases and implement some useful actions on top of it.

However, the 'if' plugin is still useful for one particular task: to raise flags that can be queried in other plugin's conditionals. Flags have a file-wide scope: they are remembered for a particular source file and its localized copies, and are shared across multiple callback plugins within a job. For example, you can set up a generic 'if' plugin tied to after_load_source_file_for_processing phase, which would analyze the source file content and set some flag, in a combination with a run_command plugin tied to after_save_localized_file phase that can do something with the localized file only if that particular flag is set (see the example below).

Example

example-project.serge

Logical statements are defined as follows:

  1. Plugin's data { ... } section may contain one or more if { ... } blocks. They are combined using logical 'OR'. This means that at least one of them must evaluate to a 'true' value: result = (block1 || block2 || block3 || ...) Note that if if { ... } block contains set_flag or remove_flag directives, it will always be processed, even if the previous if block already evaluates to a 'true' value.
  2. Each if { ... } block can contain one or more statements. All statements must evaluate to 'true' (logical 'AND'): blockN = (statement1 && statement2 && statement3 && ...) Action statements, like set_flag and remove_flag, are ignored at this point (or you can treat them as always evaluating to 'true').
  3. Each positive statement (*_matches and has_flag) can contain one or more matching rules. Multiple rules are combined using logical 'OR': statementN = (rule1 || rule2 || rule3 || ...)
  4. Each negative statement (*_doesnt_match and has_no_flag) can contain one or more matching rules. Multiple rules are combined using logical 'OR', and then negated: statementN = !(rule1 || rule2 || rule3 || ...) Which is equivalent to: statementN = (!rule1 && !rule2 && !rule3 && ...) (which means 'none of the rules should match').
  5. has_all_flags statement returns true only if all flags are set (logical 'AND'): has_all_flags = (flag1 && flag2 && flag3 && ...)
  6. Each rule for *_matches and *_doesnt_match statement represents a regular expression to check a particular value against. Regular expression matches are always case-sensitive.
  7. Each rule for has_flag, has_no_flag, and has_all_flags statement represents an exact flag name (plain string, not a regular expression).
  8. if → then block (it's actions inside, like set_flag and remove_flag) will take effect only when all conditional statements within the parent if block evaluate to 'true'.

Usage

example-project.serge