Multiple Conditions (Logical AND)
Действие выполняется, когда все условия выполняются.
<condition field="destination_number" expression="^500$"/> <condition wday="1"> action(s)... </condition>
— здесь action выполняется только если destination_number=500 и день недели — воскресенье. Если хоть одно из условий вернет false, Freeswitch перейдет к anti-action, а если anti-action не задан, то к следующему extension.
Nested Conditions — вложенные условия
require-nested — важный атрибут в nested conditions. Этот атрибут определяет, должно ли вложенное условие (sub-condition) вернуть значение true, чтобы выполнился action в родительском условии (top-level condition). Принимает значения: true или false;
Default: require-nested=true.
Если require-nested=true — sub-condition тоже должно вернуть true или иметь параметр break=never, чтобы выполнился action в родительском condition. При этом выполняются action, определенные и в sub-condition, и в top-level condition — и именно в таком порядке — сначала выполняются все action во всех sub-condition, а только потом все action в top-level condition (порядок записи не играет роли — даже если сначала записан action, а потом описан sub-condition).
! Обрабатываются сначала вложенные condition
Если require-nested=false — то неважно, что вернет sub-condition, action в родительком condition в любом случае выполнится.
break — флаг condition — при каком результате проверки условия остановить обработку данного extension и перейти к следующему extension. Принимает значения: on-false, on-true, never;
Default: break=on-false;
break можно указывать в цепочке из условий, например, при создании логики Logical AND.
break применяется и в nested conditions (sub-condition). В обычной работе без указания данного флага (при require-nested=true и break=on-false — это дефолтные значения), если первый sub-condition возвращает false, то следующий (sub)-condition (если он есть) уже не проверяется, и в целом работа с данным extension прекращается и парсится уже следующий extension.
Так вот, если указать в первом sub-condition break=never, то даже если он вернет false, следующий за ним sub-condition проверяться будет!
Пример:
в top-level condition указан require-nested=false — результат проверки вложенных условий не повлияет на выполнение action в родительском condition); в sub-condition’ах указан флаг break=never — не прерывать выполнение всего extension, разрешить проверку следующих condition.
<extension name="nested_example"> <condition field="destination_number" expression="^1234$" require-nested="false"> <action application="log" data="INFO I'm before the nested conditions..."/> <condition field="${foo1}" expression="bar1" break="never"> <action application="log" data="INFO foo1 is bar1" /> </condition> <action application="log" data="INFO I'm in between the nested conditions..."/> <condition field="${foo2}" expression="bar2" break="never"> <action application="log" data="INFO foo2 is bar2" /> </condition> <action application="log" data="INFO I'm after the nested conditions..."/> </condition </extension>
Для чего break=never для второго sub-condition? Ведь после него больше sub-condition нет. Да, но после второго sub-condition еще есть top-level condition, ведь проверка условий будет выполняться в следующем порядке: sub-condition 1, sub-condition 2, top-level condition — сначала по порядку все вложенные, и только потом родитель.
В итоге после выполнения данного extension у нас в логах будут записи в такой очередности:
<action application="log" data="INFO foo1 is bar1" /> <action application="log" data="INFO foo2 is bar2" /> <action application="log" data="INFO I'm before the nested conditions..."/> <action application="log" data="INFO I'm in between the nested conditions..."/> <action application="log" data="INFO I'm after the nested conditions..."/>
Multiple Conditions (Logical OR, XOR)
Логическое ИЛИ — action выполняется, если хоть одно из условий возвращет true.
Если ИЛИ нужно организовать для одного поля, т.е. смотрим только на одну переменную, то можно воспользоваться следующей конструкцией:
<condition field="destination_number" expression="^501|502$"> action(s)... </condition>
— action будет выполнен, если destination_number 501 ИЛИ 502.
Если ИЛИ для разных полей, используется regex.
<condition regex="all|any|xor"> <regex field="some_field" expression="Some Value"/> <regex field="another_field" expression="^Another\s*Value$"/> <action(s) ...> <anti-action(s)...> </condition>
regex может иметь следующие значения:
- all — logical AND — все условия должны вернуть true, чтобы выполнилось action;
- any — logical OR — хотя бы одно из условий должны возвратить true, чтобы выполнилось action;
- xor — logical XOR — только одно условие должно возвратить true, чтобы выполнилось action;
Комплексный пример — маршрутизация по времени (time-based routing):
Пользователь звонит на extension 1100. Вызов перенаправляется на extension 1105 с понедельника по четверг с 8:00 до 21:59. В пятницу звонок перенаправляется на 1105 с 8:00 до 12:59. Во все остальное время вызовы перенаправляются в голосовую почту.
<extension name="Time-of-day-tod"> <!--если это условие false, FreeSWITCH переходит к следующему *extension*.--> <condition field="destination_number" expression="^1100$" break="on-false"/> <!-- Если это условие возвращает true, следующее уже не проверяем--> <condition wday="6" hour="8-12" break="on-true"> <!--пятница с 8 до 12:59 --> <action application="transfer" data="1105 XML default"/> </condition> <condition wday="2-5" hour="8-21" break="on-true"> <!--понедельник-четверг с 8 до 21:59--> <action application="transfer" data="1105 XML default"/> </condition> <condition> <!-- перенаправление в голосовую почту в остальное время --> <action application="voicemail" data="default ${domain} 1105"/> </condition> </extension>
— в первом condition в данном примере можно было и не указывать break=on-false, ведь это значение по умолчанию, если не задано другое.