mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-07 01:18:44 +02:00
Compare commits
12 Commits
feature/81
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ac675a587 | ||
|
|
769afb2715 | ||
|
|
b529a61bc5 | ||
|
|
c501280f53 | ||
|
|
e662370c32 | ||
|
|
3c39c6d8d1 | ||
|
|
a7d0262b21 | ||
|
|
c56617abf5 | ||
|
|
ff94639a61 | ||
|
|
7676115725 | ||
|
|
43ceaeb5a3 | ||
|
|
7cac280b83 |
@@ -54,6 +54,15 @@
|
||||
</modules>
|
||||
<default>true</default>
|
||||
</choice>
|
||||
<choice>
|
||||
<extension_code>itop-flow-map</extension_code>
|
||||
<title>Application Data Flows</title>
|
||||
<description>Modelize flows between your applications, with impacts analysis</description>
|
||||
<modules type="array">
|
||||
<module>itop-flow-map</module>
|
||||
</modules>
|
||||
<default>true</default>
|
||||
</choice>
|
||||
<choice>
|
||||
<extension_code>itop-config-mgmt-storage</extension_code>
|
||||
<title>Storage Devices</title>
|
||||
@@ -80,11 +89,20 @@
|
||||
<modules type="array">
|
||||
<module>itop-container-mgmt</module>
|
||||
</modules>
|
||||
<default>false</default>
|
||||
<default>true</default>
|
||||
</choice>
|
||||
</options>
|
||||
</sub_options>
|
||||
</choice>
|
||||
<choice>
|
||||
<extension_code>itop-flow-map</extension_code>
|
||||
<title>Data flow</title>
|
||||
<description>Map data flows between applications</description>
|
||||
<modules type="array">
|
||||
<module>itop-flow-map</module>
|
||||
</modules>
|
||||
<default>false</default>
|
||||
</choice>
|
||||
</options>
|
||||
</step>
|
||||
<step>
|
||||
|
||||
@@ -167,7 +167,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:Rack' => 'Rack',
|
||||
'Class:Rack+' => 'A physical cabinet for Datacenter Devices and Chassis.',
|
||||
'Class:Rack+' => 'A physical cabinet for Datacenter Devices and Enclosures.',
|
||||
'Class:Rack/ComplementaryName' => '%1$s - %2$s',
|
||||
'Class:Rack/Attribute:nb_u' => 'Rack units',
|
||||
'Class:Rack/Attribute:nb_u+' => '',
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<DataFlowType alias="DataFlowType" id="1">
|
||||
<name>http</name>
|
||||
</DataFlowType>
|
||||
<DataFlowType alias="DataFlowType" id="2">
|
||||
<name>https</name>
|
||||
</DataFlowType>
|
||||
<DataFlowType alias="DataFlowType" id="3">
|
||||
<name>ftp</name>
|
||||
</DataFlowType>
|
||||
<DataFlowType alias="DataFlowType" id="4">
|
||||
<name>sftp</name>
|
||||
</DataFlowType>
|
||||
<DataFlowType alias="DataFlowType" id="5">
|
||||
<name>AS2</name>
|
||||
</DataFlowType>
|
||||
<DataFlowType alias="DataFlowType" id="6">
|
||||
<name>X.400</name>
|
||||
</DataFlowType>
|
||||
</Set>
|
||||
750
datamodels/2.x/itop-flow-map/datamodel.itop-flow-map.xml
Normal file
750
datamodels/2.x/itop-flow-map/datamodel.itop-flow-map.xml
Normal file
@@ -0,0 +1,750 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3">
|
||||
<classes>
|
||||
<class id="DataFlow" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<category>bizmodel,searchable</category>
|
||||
<abstract>false</abstract>
|
||||
<db_table>dataflow</db_table>
|
||||
<style>
|
||||
<icon>images/icons8-sorting-arrows-horizontal.svg</icon>
|
||||
</style>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="name"/>
|
||||
<attribute id="destination_id"/>
|
||||
<attribute id="org_id"/>
|
||||
<attribute id="source_id"/>
|
||||
<attribute id="dataflowtype_id"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<obsolescence>
|
||||
<condition>status='inactive'</condition>
|
||||
</obsolescence>
|
||||
<fields_semantic>
|
||||
<state_attribute>status</state_attribute>
|
||||
</fields_semantic>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="name" xsi:type="AttributeString">
|
||||
<sql>name</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="org_id" xsi:type="AttributeExternalKey">
|
||||
<sql>org_id</sql>
|
||||
<filter/>
|
||||
<dependencies/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<target_class>Organization</target_class>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="source_id" xsi:type="AttributeExternalKey">
|
||||
<sql>source_id</sql>
|
||||
<filter/>
|
||||
<dependencies/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<target_class>FunctionalCI</target_class>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="source_impact" xsi:type="AttributeEnum">
|
||||
<sort_type>rank</sort_type>
|
||||
<values>
|
||||
<value id="yes">
|
||||
<code>yes</code>
|
||||
<rank>10</rank>
|
||||
</value>
|
||||
<value id="no">
|
||||
<code>no</code>
|
||||
<rank>20</rank>
|
||||
</value>
|
||||
</values>
|
||||
<sql>source_impact</sql>
|
||||
<default_value>yes</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<display_style>radio_horizontal</display_style>
|
||||
</field>
|
||||
<field id="destination_id" xsi:type="AttributeExternalKey">
|
||||
<sql>destination_id</sql>
|
||||
<filter/>
|
||||
<dependencies/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<target_class>FunctionalCI</target_class>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="destination_impact" xsi:type="AttributeEnum">
|
||||
<sort_type>rank</sort_type>
|
||||
<values>
|
||||
<value id="yes">
|
||||
<code>yes</code>
|
||||
<rank>10</rank>
|
||||
</value>
|
||||
<value id="no">
|
||||
<code>no</code>
|
||||
<rank>20</rank>
|
||||
</value>
|
||||
</values>
|
||||
<sql>destination_impact</sql>
|
||||
<default_value>no</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<display_style>radio_horizontal</display_style>
|
||||
</field>
|
||||
<field id="dataflowtype_id" xsi:type="AttributeExternalKey">
|
||||
<sql>dataflowtype_id</sql>
|
||||
<filter/>
|
||||
<dependencies/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<target_class>DataFlowType</target_class>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="description" xsi:type="AttributeHTML">
|
||||
<sql>description</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<sql>status</sql>
|
||||
<values>
|
||||
<value id="active">
|
||||
<code>active</code>
|
||||
<rank>10</rank>
|
||||
<style>
|
||||
<main_color>$ibo-lifecycle-active-state-primary-color</main_color>
|
||||
<complementary_color>$ibo-lifecycle-active-state-secondary-color</complementary_color>
|
||||
<decoration_classes/>
|
||||
</style>
|
||||
</value>
|
||||
<value id="inactive">
|
||||
<code>inactive</code>
|
||||
<rank>20</rank>
|
||||
<style>
|
||||
<main_color>$ibo-lifecycle-inactive-state-primary-color</main_color>
|
||||
<complementary_color>$ibo-lifecycle-inactive-state-secondary-color</complementary_color>
|
||||
<decoration_classes/>
|
||||
</style>
|
||||
</value>
|
||||
</values>
|
||||
<sort_type>label</sort_type>
|
||||
<default_value>active</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<display_style>list</display_style>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="business_criticity" xsi:type="AttributeEnum">
|
||||
<sort_type>rank</sort_type>
|
||||
<values>
|
||||
<value id="high">
|
||||
<code>high</code>
|
||||
<rank>10</rank>
|
||||
</value>
|
||||
<value id="medium">
|
||||
<code>medium</code>
|
||||
<rank>20</rank>
|
||||
</value>
|
||||
<value id="low">
|
||||
<code>low</code>
|
||||
<rank>30</rank>
|
||||
</value>
|
||||
</values>
|
||||
<sql>business_criticity</sql>
|
||||
<default_value>low</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<display_style>list</display_style>
|
||||
</field>
|
||||
<field id="execution_frequency" xsi:type="AttributeEnum">
|
||||
<sort_type>rank</sort_type>
|
||||
<values>
|
||||
<value id="realtime">
|
||||
<code>realtime</code>
|
||||
<rank>10</rank>
|
||||
</value>
|
||||
<value id="ondemand">
|
||||
<code>ondemand</code>
|
||||
<rank>20</rank>
|
||||
</value>
|
||||
<value id="hourly">
|
||||
<code>hourly</code>
|
||||
<rank>30</rank>
|
||||
</value>
|
||||
<value id="daily">
|
||||
<code>daily</code>
|
||||
<rank>40</rank>
|
||||
</value>
|
||||
<value id="weekly">
|
||||
<code>weekly</code>
|
||||
<rank>50</rank>
|
||||
</value>
|
||||
<value id="monthly">
|
||||
<code>monthly</code>
|
||||
<rank>60</rank>
|
||||
</value>
|
||||
<value id="yearly">
|
||||
<code>yearly</code>
|
||||
<rank>70</rank>
|
||||
</value>
|
||||
</values>
|
||||
<sql>execution_frequency</sql>
|
||||
<default_value>daily</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<display_style>list</display_style>
|
||||
</field>
|
||||
<field id="contacts_list" xsi:type="AttributeLinkedSetIndirect">
|
||||
<linked_class>lnkContactToDataFlow</linked_class>
|
||||
<ext_key_to_me>dataflow_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<ext_key_to_remote>contact_id</ext_key_to_remote>
|
||||
<duplicates/>
|
||||
</field>
|
||||
<field id="documents_list" xsi:type="AttributeLinkedSetIndirect">
|
||||
<linked_class>lnkDocumentToDataFlow</linked_class>
|
||||
<ext_key_to_me>dataflow_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<ext_key_to_remote>document_id</ext_key_to_remote>
|
||||
<duplicates/>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<list>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="source_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="destination_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="dataflowtype_id">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="business_criticity">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<search>
|
||||
<items>
|
||||
<item id="org_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="source_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="destination_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<details>
|
||||
<items>
|
||||
<item id="col:col1">
|
||||
<items>
|
||||
<item id="fieldset:DataFlow:baseinfo">
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="business_criticity">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
</items>
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="fieldset:DataFlow:moreinfo">
|
||||
<items>
|
||||
<item id="source_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="source_impact">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="destination_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="destination_impact">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="dataflowtype_id">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="execution_frequency">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
</items>
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="col:col2">
|
||||
<items>
|
||||
<item id="fieldset:DataFlow:otherinfo">
|
||||
<items>
|
||||
<item id="description">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="contacts_list">
|
||||
<rank>70</rank>
|
||||
</item>
|
||||
<item id="documents_list">
|
||||
<rank>80</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<default_search>
|
||||
<items>
|
||||
<item id="org_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="source_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="destination_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="dataflowtype_id">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</default_search>
|
||||
<summary>
|
||||
<items>
|
||||
<item id="org_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</summary>
|
||||
</presentation>
|
||||
<relations>
|
||||
<relation id="impacts">
|
||||
<neighbours>
|
||||
<neighbour id="functionalci ">
|
||||
<query_down><![CDATA[SELECT FunctionalCI WHERE :this->destination_impact = 'yes' AND id = :this->destination_id]]></query_down>
|
||||
<query_up><![CDATA[SELECT DataFlow AS f JOIN FunctionalCI AS ci ON f.destination_id = ci.id WHERE f.destination_impact = 'yes' AND ci.id=:this->id]]></query_up>
|
||||
<direction>both</direction>
|
||||
</neighbour>
|
||||
<neighbour id="contact ">
|
||||
<attribute>contacts_list</attribute>
|
||||
<direction>down</direction>
|
||||
</neighbour>
|
||||
</neighbours>
|
||||
</relation>
|
||||
</relations>
|
||||
</class>
|
||||
<class id="lnkDocumentToDataFlow" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<is_link>1</is_link>
|
||||
<category>bizmodel</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>lnkdocumenttodataflow</db_table>
|
||||
<db_key_field>id</db_key_field>
|
||||
<db_final_class_field/>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="document_id_friendlyname"/>
|
||||
<attribute id="dataflow_id_friendlyname"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="dataflow_id"/>
|
||||
<attribute id="document_id"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<uniqueness_rules>
|
||||
<rule id="no_duplicate">
|
||||
<attributes>
|
||||
<attribute id="document_id"/>
|
||||
<attribute id="dataflow_id"/>
|
||||
</attributes>
|
||||
<filter><![CDATA[]]></filter>
|
||||
<disabled>false</disabled>
|
||||
<is_blocking>true</is_blocking>
|
||||
</rule>
|
||||
</uniqueness_rules>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="dataflow_id" xsi:type="AttributeExternalKey">
|
||||
<sql>dataflow_id</sql>
|
||||
<target_class>DataFlow</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
</field>
|
||||
<field id="document_id" xsi:type="AttributeExternalKey">
|
||||
<sql>document_id</sql>
|
||||
<target_class>Document</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="document_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="dataflow_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item id="dataflow_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="document_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="dataflow_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="document_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="lnkContactToDataFlow" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<is_link>1</is_link>
|
||||
<category>bizmodel</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>lnkcontacttodataflow</db_table>
|
||||
<db_key_field>id</db_key_field>
|
||||
<db_final_class_field/>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="contact_id_friendlyname"/>
|
||||
<attribute id="dataflow_id_friendlyname"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<style>
|
||||
<icon/>
|
||||
</style>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="dataflow_id"/>
|
||||
<attribute id="contact_id"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
<uniqueness_rules>
|
||||
<rule id="no_duplicate">
|
||||
<attributes>
|
||||
<attribute id="contact_id"/>
|
||||
<attribute id="dataflow_id"/>
|
||||
</attributes>
|
||||
<filter><![CDATA[]]></filter>
|
||||
<disabled>false</disabled>
|
||||
<is_blocking>true</is_blocking>
|
||||
</rule>
|
||||
</uniqueness_rules>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="dataflow_id" xsi:type="AttributeExternalKey">
|
||||
<sql>dataflow_id</sql>
|
||||
<target_class>DataFlow</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
</field>
|
||||
<field id="contact_id" xsi:type="AttributeExternalKey">
|
||||
<sql>contact_id</sql>
|
||||
<target_class>Contact</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="contact_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="dataflow_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item id="dataflow_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="contact_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="dataflow_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="contact_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="DataFlowType" _delta="define">
|
||||
<parent>Typology</parent>
|
||||
<properties>
|
||||
<category>bizmodel,searchable</category>
|
||||
<abstract>false</abstract>
|
||||
<db_table>dataflowtype</db_table>
|
||||
<naming>
|
||||
<attributes>
|
||||
<attribute id="name"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="name"/>
|
||||
<attribute id="finalclass"/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
</properties>
|
||||
<fields/>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<list>
|
||||
<items>
|
||||
<item id="finalclass">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
<search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<details>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="FunctionalCI" _delta="must_exist">
|
||||
<fields>
|
||||
<field id="dataflows" xsi:type="AttributeDashboard" _delta="define">
|
||||
<is_user_editable>true</is_user_editable>
|
||||
<definition>
|
||||
<layout>DashboardLayoutTwoCols</layout>
|
||||
<title>FunctionalCI:DataFlow:Title</title>
|
||||
<auto_reload>
|
||||
<enabled>false</enabled>
|
||||
<interval>300</interval>
|
||||
</auto_reload>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="DataFlow_Inbound" xsi:type="DashletObjectList">
|
||||
<rank>0</rank>
|
||||
<title>FunctionalCI:DataFlow:Inbound</title>
|
||||
<query>SELECT DataFlow WHERE destination_id=:this->id</query>
|
||||
<menu>true</menu>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="1">
|
||||
<rank>1</rank>
|
||||
<dashlets>
|
||||
<dashlet id="DataFlow_Outbound" xsi:type="DashletObjectList">
|
||||
<rank>0</rank>
|
||||
<title>FunctionalCI:DataFlow:Outbound</title>
|
||||
<query>SELECT DataFlow WHERE source_id=:this->id</query>
|
||||
<menu>true</menu>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</field>
|
||||
</fields>
|
||||
<relations>
|
||||
<relation id="impacts">
|
||||
<neighbours>
|
||||
<neighbour id="flow" _delta="define">
|
||||
<query_down><![CDATA[SELECT DataFlow WHERE source_id = :this->id AND source_impact = 'yes']]></query_down>
|
||||
<query_up><![CDATA[SELECT FunctionalCI AS ci JOIN DataFlow AS f ON f.source_id = ci.id WHERE f.source_impact = 'yes' AND f.id = :this->id]]></query_up>
|
||||
<direction>both</direction>
|
||||
</neighbour>
|
||||
</neighbours>
|
||||
</relation>
|
||||
</relations>
|
||||
</class>
|
||||
<class id="ApplicationSolution" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="DatabaseSchema" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="DBServer" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="Middleware" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="MiddlewareInstance" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="WebApplication" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="WebServer" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="OtherSoftware" _delta="must_exist">
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="dataflows" _delta="define">
|
||||
<rank>25</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="3" delta="if_exists">
|
||||
<dashlets>
|
||||
<dashlet id="DataFlow_20" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>20</rank>
|
||||
<class>DataFlow</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
<user_rights>
|
||||
<groups>
|
||||
<group id="Configuration">
|
||||
<classes>
|
||||
<class id="DataFlow" _delta="define_if_not_exists"/>
|
||||
</classes>
|
||||
</group>
|
||||
</groups>
|
||||
<profiles>
|
||||
</profiles>
|
||||
</user_rights>
|
||||
</itop_design>
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Module combodo-flow-map
|
||||
*
|
||||
* @copyright Copyright (C) 2013 XXXXX
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
|
||||
'Class:FunctionalCI/Attribute:dataflows' => 'Data flows',
|
||||
'Class:FunctionalCI/Attribute:dataflows+' => 'Data flows for which this object is the source or the destination',
|
||||
'FunctionalCI:DataFlow:Title' => 'Data flows',
|
||||
'FunctionalCI:DataFlow:Inbound' => 'Inbound flows',
|
||||
'FunctionalCI:DataFlow:Outbound' => 'Outbound flows',
|
||||
|
||||
'DataFlow:baseinfo' => 'General information',
|
||||
'DataFlow:otherinfo' => 'Other information',
|
||||
'DataFlow:moreinfo' => 'Flow specifics',
|
||||
|
||||
'Class:DataFlow' => 'Flow',
|
||||
'Class:DataFlow+' => 'For application flow for example',
|
||||
'Class:DataFlow/Name' => '%1$s',
|
||||
'Class:DataFlow/Attribute:name' => 'Name',
|
||||
'Class:DataFlow/Attribute:name_id+' => 'Data that are transferred',
|
||||
'Class:DataFlow/Attribute:source_id' => 'Source',
|
||||
'Class:DataFlow/Attribute:source_id+' => 'Source Ci of the flow',
|
||||
'Class:DataFlow/Attribute:source_impact' => 'Source impacts?',
|
||||
'Class:DataFlow/Attribute:source_impact+' => 'Does the source impact the flow?',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:yes' => 'yes',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:yes+' => 'If the source falls down, the flow is impacted',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:no' => 'no',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:no+' => 'If the source falls down, the flow is not impacted',
|
||||
'Class:DataFlow/Attribute:destination_id' => 'Destination',
|
||||
'Class:DataFlow/Attribute:destination_id+' => 'Destination Ci for the flow',
|
||||
'Class:DataFlow/Attribute:destination_impact' => 'Destination impacted',
|
||||
'Class:DataFlow/Attribute:destination_impact+' => 'Is the destination impacted by the flow ?',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:yes' => 'yes',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:yes+' => 'If the flow stops, the destination is impacted',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:no' => 'no',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:no+' => 'If the flow stops, the destination is not impacted',
|
||||
'Class:DataFlow/Attribute:dataflowtype_id' => 'Flow type',
|
||||
'Class:DataFlow/Attribute:dataflowtype_id+' => 'Typology of Flow.',
|
||||
'Class:DataFlow/Attribute:description' => 'Description',
|
||||
'Class:DataFlow/Attribute:description+' => '',
|
||||
'Class:DataFlow/Attribute:status' => 'Status',
|
||||
'Class:DataFlow/Attribute:status+' => '',
|
||||
'Class:DataFlow/Attribute:status/Value:active' => 'active',
|
||||
'Class:DataFlow/Attribute:status/Value:inactive' => 'inactive',
|
||||
'Class:DataFlow/Attribute:org_id' => 'Organization',
|
||||
'Class:DataFlow/Attribute:org_id+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity' => 'Business criticality',
|
||||
'Class:DataFlow/Attribute:business_criticity+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:high' => 'high',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:high+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:low' => 'low',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:low+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:medium' => 'medium',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:medium+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency' => 'Execution frequency',
|
||||
'Class:DataFlow/Attribute:execution_frequency+' => 'How often the data flow is executed',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:realtime' => 'real-time',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:realtime+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:ondemand' => 'on demand',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:ondemand+' => 'on the fly, not scheduled',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:hourly' => 'hourly',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:hourly+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:daily' => 'daily',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:daily+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:weekly' => 'weekly',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:weekly+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:monthly' => 'monthly',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:monthly+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:yearly' => 'yearly',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:yearly+' => '',
|
||||
'Class:DataFlow/Attribute:documents_list' => 'Documents',
|
||||
'Class:DataFlow/Attribute:documents_list+' => 'Eg: technical specifications, runbooks, etc.',
|
||||
'Class:DataFlow/Attribute:contacts_list' => 'Contacts',
|
||||
'Class:DataFlow/Attribute:contacts_list+' => 'Eg: flow owner, technical support, etc.',
|
||||
|
||||
/*
|
||||
'Class:DataFlow/Attribute:source_id_friendlyname' => 'source_id_friendlyname',
|
||||
'Class:DataFlow/Attribute:source_id_friendlyname+' => 'Full name',
|
||||
'Class:DataFlow/Attribute:source_id_finalclass_recall' => 'source_id->CI sub-class',
|
||||
'Class:DataFlow/Attribute:source_id_finalclass_recall+' => 'Name of the final class',
|
||||
'Class:DataFlow/Attribute:source_id_obsolescence_flag' => 'source_id->Obsolete',
|
||||
'Class:DataFlow/Attribute:source_id_obsolescence_flag+' => 'Computed dynamically on other attributes',
|
||||
'Class:DataFlow/Attribute:destination_id_friendlyname' => 'destination_id_friendlyname',
|
||||
'Class:DataFlow/Attribute:destination_id_friendlyname+' => 'Full name',
|
||||
'Class:DataFlow/Attribute:destination_id_finalclass_recall' => 'destination_id->CI sub-class',
|
||||
'Class:DataFlow/Attribute:destination_id_finalclass_recall+' => 'Name of the final class',
|
||||
'Class:DataFlow/Attribute:destination_id_obsolescence_flag' => 'destination_id->Obsolete',
|
||||
'Class:DataFlow/Attribute:destination_id_obsolescence_flag+' => 'Computed dynamically on other attributes',
|
||||
*/
|
||||
]);
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Module combodo-flow-map
|
||||
*
|
||||
* @copyright Copyright (C) 2013 XXXXX
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
|
||||
'Class:FunctionalCI/Attribute:dataflows' => 'Flux de données',
|
||||
'Class:FunctionalCI/Attribute:dataflows+' => 'Flux de données dont cet objet est la source ou la destination',
|
||||
'FunctionalCI:DataFlow:Title' => 'Flux de données',
|
||||
'FunctionalCI:DataFlow:Inbound' => 'Flux entrants',
|
||||
'FunctionalCI:DataFlow:Outbound' => 'Flux sortants',
|
||||
|
||||
'DataFlow:baseinfo' => 'Informations générales',
|
||||
'DataFlow:otherinfo' => 'Autres informations',
|
||||
'DataFlow:moreinfo' => 'Spécificités du flux',
|
||||
|
||||
'Class:DataFlow' => 'Flux de Données',
|
||||
'Class:DataFlow+' => 'Modélise les données transférées entre instances d\'application',
|
||||
'Class:DataFlow/Name' => '%1$s',
|
||||
'Class:DataFlow/Attribute:name' => 'Nom',
|
||||
'Class:DataFlow/Attribute:name_id+' => 'Type de données transferées',
|
||||
'Class:DataFlow/Attribute:source_id' => 'Source',
|
||||
'Class:DataFlow/Attribute:source_id+' => 'Instance d\application à la source du flux de données',
|
||||
'Class:DataFlow/Attribute:source_impact' => 'Source impactante ?',
|
||||
'Class:DataFlow/Attribute:source_impact+' => 'La source impacte-t-elle le flux de données ?',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:yes' => 'oui',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:yes+' => 'Si la source tombe en panne, le flux de données est impacté',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:no' => 'non',
|
||||
'Class:DataFlow/Attribute:source_impact/Value:no+' => 'Si la source tombe en panne, le flux de données n\'est pas impacté',
|
||||
'Class:DataFlow/Attribute:destination_id' => 'Destinataire',
|
||||
'Class:DataFlow/Attribute:destination_id+' => 'Destinataire des données, à choisir parmi les instances d\'application',
|
||||
'Class:DataFlow/Attribute:destination_impact' => 'Destinataire impacté ?',
|
||||
'Class:DataFlow/Attribute:destination_impact+' => 'Le destinataire est-il impacté si le flux de données s\'arrête ?',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:yes' => 'oui',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:yes+' => 'Si le flux s\'arrête, le destinataire est impacté',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:no' => 'non',
|
||||
'Class:DataFlow/Attribute:destination_impact/Value:no+' => 'Si le flux s\'arrête, le destinataire n\'est pas impacté',
|
||||
'Class:DataFlow/Attribute:dataflowtype_id' => 'Type de flux',
|
||||
'Class:DataFlow/Attribute:dataflowtype_id+' => 'Typologie du flux',
|
||||
'Class:DataFlow/Attribute:description' => 'Description',
|
||||
'Class:DataFlow/Attribute:description+' => '',
|
||||
'Class:DataFlow/Attribute:status' => 'Etat',
|
||||
'Class:DataFlow/Attribute:status+' => '',
|
||||
'Class:DataFlow/Attribute:status/Value:active' => 'actif',
|
||||
'Class:DataFlow/Attribute:status/Value:inactive' => 'inactif',
|
||||
'Class:DataFlow/Attribute:org_id' => 'Organisation',
|
||||
'Class:DataFlow/Attribute:org_id+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity' => 'Criticité',
|
||||
'Class:DataFlow/Attribute:business_criticity+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:high' => 'haute',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:high+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:low' => 'basse',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:low+' => '',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:medium' => 'moyenne',
|
||||
'Class:DataFlow/Attribute:business_criticity/Value:medium+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency' => 'Fréquence d\'exécution',
|
||||
'Class:DataFlow/Attribute:execution_frequency+' => 'À quelle fréquence le transfert de données est-il exécuté',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:realtime' => 'temps réel',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:realtime+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:ondemand' => 'à la demande',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:ondemand+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:hourly' => 'horaire',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:hourly+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:daily' => 'journalière',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:daily+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:weekly' => 'hebdomadaire',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:weekly+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:monthly' => 'mensuelle',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:monthly+' => '',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:yearly' => 'annuelle',
|
||||
'Class:DataFlow/Attribute:execution_frequency/Value:yearly+' => '',
|
||||
'Class:DataFlow/Attribute:documents_list' => 'Documents',
|
||||
'Class:DataFlow/Attribute:documents_list+' => 'Eg: technical specifications, runbooks, etc.',
|
||||
'Class:DataFlow/Attribute:contacts_list' => 'Contacts',
|
||||
'Class:DataFlow/Attribute:contacts_list+' => 'Eg: flow owner, technical support, etc.',
|
||||
|
||||
/*
|
||||
'Class:DataFlow/Attribute:source_id_friendlyname' => 'source_id_friendlyname',
|
||||
'Class:DataFlow/Attribute:source_id_friendlyname+' => 'Nom complet',
|
||||
'Class:DataFlow/Attribute:source_id_finalclass_recall' => 'source_id->CI sub-class',
|
||||
'Class:DataFlow/Attribute:source_id_finalclass_recall+' => 'Classe finale',
|
||||
'Class:DataFlow/Attribute:source_id_obsolescence_flag' => 'source_id->Obsolete',
|
||||
'Class:DataFlow/Attribute:source_id_obsolescence_flag+' => 'Computed dynamically on other attributes',
|
||||
'Class:DataFlow/Attribute:destination_id_friendlyname' => 'destination_id_friendlyname',
|
||||
'Class:DataFlow/Attribute:destination_id_friendlyname+' => 'Nom complet',
|
||||
'Class:DataFlow/Attribute:destination_id_finalclass_recall' => 'destination_id->CI sub-class',
|
||||
'Class:DataFlow/Attribute:destination_id_finalclass_recall+' => 'Classe finale',
|
||||
'Class:DataFlow/Attribute:destination_id_obsolescence_flag' => 'destination_id->Obsolete',
|
||||
'Class:DataFlow/Attribute:destination_id_obsolescence_flag+' => 'Computed dynamically on other attributes',
|
||||
*/
|
||||
]);
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="96px" height="96px"><linearGradient id="mv_DwPz_GcV~datTQ_sP3a" x1="27.258" x2="38.501" y1="18.189" y2="44.314" gradientTransform="rotate(90 23.5 24)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32bdef"/><stop offset="1" stop-color="#1ea2e4"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3a)" d="M14,41.19V37h14c0.552,0,1-0.448,1-1v-4c0-0.552-0.448-1-1-1H14v-4.19 c0-0.72-0.87-1.08-1.379-0.571L5.92,32.939c-0.586,0.586-0.586,1.536,0,2.121l6.701,6.701C13.13,42.271,14,41.91,14,41.19z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3b" x1="32.674" x2="34.456" y1="9.581" y2="13.722" gradientTransform="rotate(90 23.5 24)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32bdef"/><stop offset="1" stop-color="#1ea2e4"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3b)" d="M35,36v-4c0-0.552,0.448-1,1-1l0,0c0.552,0,1,0.448,1,1v4c0,0.552-0.448,1-1,1l0,0 C35.448,37,35,36.552,35,36z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3c" x1="32.674" x2="34.456" y1="5.581" y2="9.722" gradientTransform="rotate(90 23.5 24)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32bdef"/><stop offset="1" stop-color="#1ea2e4"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3c)" d="M39,36v-4c0-0.552,0.448-1,1-1l0,0c0.552,0,1,0.448,1,1v4c0,0.552-0.448,1-1,1l0,0 C39.448,37,39,36.552,39,36z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3d" x1="32.674" x2="34.456" y1="13.581" y2="17.722" gradientTransform="rotate(90 23.5 24)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#32bdef"/><stop offset="1" stop-color="#1ea2e4"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3d)" d="M31,36v-4c0-0.552,0.448-1,1-1h0c0.552,0,1,0.448,1,1v4c0,0.552-0.448,1-1,1h0 C31.448,37,31,36.552,31,36z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3e" x1="551.258" x2="562.501" y1="-252.291" y2="-226.167" gradientTransform="rotate(-90 421.24 151.26)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1ea2e4"/><stop offset="1" stop-color="#32bdef"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3e)" d="M33,7.81V12H19c-0.552,0-1,0.448-1,1v4c0,0.552,0.448,1,1,1h14v4.19 c0,0.72,0.87,1.08,1.379,0.571l6.701-6.701c0.586-0.586,0.586-1.536,0-2.121l-6.701-6.701C33.87,6.729,33,7.09,33,7.81z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3f" x1="556.674" x2="558.456" y1="-260.899" y2="-256.759" gradientTransform="rotate(-90 421.24 151.26)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1ea2e4"/><stop offset="1" stop-color="#32bdef"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3f)" d="M12,13v4c0,0.552-0.448,1-1,1h0c-0.552,0-1-0.448-1-1v-4c0-0.552,0.448-1,1-1h0 C11.552,12,12,12.448,12,13z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3g" x1="556.674" x2="558.456" y1="-264.899" y2="-260.759" gradientTransform="rotate(-90 421.24 151.26)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1ea2e4"/><stop offset="1" stop-color="#32bdef"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3g)" d="M8,13v4c0,0.552-0.448,1-1,1h0c-0.552,0-1-0.448-1-1v-4c0-0.552,0.448-1,1-1h0 C7.552,12,8,12.448,8,13z"/><linearGradient id="mv_DwPz_GcV~datTQ_sP3h" x1="556.674" x2="558.456" y1="-256.899" y2="-252.758" gradientTransform="rotate(-90 421.24 151.26)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1ea2e4"/><stop offset="1" stop-color="#32bdef"/></linearGradient><path fill="url(#mv_DwPz_GcV~datTQ_sP3h)" d="M16,13v4c0,0.552-0.448,1-1,1h0c-0.552,0-1-0.448-1-1v-4c0-0.552,0.448-1,1-1h0 C15.552,12,16,12.448,16,13z"/></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
50
datamodels/2.x/itop-flow-map/module.itop-flow-map.php
Normal file
50
datamodels/2.x/itop-flow-map/module.itop-flow-map.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
//
|
||||
// iTop module definition file
|
||||
//
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-flow-map/3.3.0',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Applications data flows',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => [
|
||||
'itop-config-mgmt/3.2.0',
|
||||
],
|
||||
'mandatory' => false,
|
||||
'visible' => true,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => [
|
||||
|
||||
],
|
||||
'webservice' => [
|
||||
|
||||
],
|
||||
'data.struct' => [
|
||||
'data/en_us.data.itop-flow-map.xml',
|
||||
],
|
||||
'data.sample' => [
|
||||
// add your sample data XML files here,
|
||||
],
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => [
|
||||
// Module specific settings go here, if any
|
||||
],
|
||||
]
|
||||
);
|
||||
@@ -153,8 +153,12 @@ class Extension
|
||||
return twig_array_filter($oTwigEnv, $array, $arrow);
|
||||
}, ['needs_environment' => true]);
|
||||
|
||||
// @since 3.3.0 N°8579
|
||||
// Filter to remove spaces between HTML tags, overwrite the deprecated core "spaceless" filter
|
||||
/**
|
||||
* Filter to remove spaces between HTML tags, overwrite the deprecated core "spaceless" filter
|
||||
* Usage in twig: {% apply spaceless %}some html{% endapply %}
|
||||
*
|
||||
* @since 3.2.3 3.3.0 N°8579
|
||||
*/
|
||||
$aFilters[] = new TwigFilter('spaceless', function (?string $content) {
|
||||
return trim(preg_replace('/>\s+</', '><', $content ?? ''));
|
||||
}, ['is_safe' => ['html']]);
|
||||
|
||||
@@ -29,7 +29,9 @@ use Symfony\Component\CssSelector\Exception\ParseException;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
|
||||
use Symfony\Component\Mime\Email as SymfonyEmail;
|
||||
use Symfony\Component\Mime\HtmlToTextConverter\DefaultHtmlToTextConverter;
|
||||
use Symfony\Component\Mime\Part\DataPart;
|
||||
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
|
||||
use Symfony\Component\Mime\Part\Multipart\MixedPart;
|
||||
@@ -183,18 +185,7 @@ class EMailSymfony extends Email
|
||||
$sDsn = sprintf('smtp://%s%s@%s%s', $sDsnUser, $sDsnPassword, $sDsnPort, $sEncQuery);
|
||||
}
|
||||
|
||||
$oTransport = Transport::fromDsn($sDsn);
|
||||
|
||||
// Handle peer verification
|
||||
$oStream = $oTransport->getStream();
|
||||
$aOptions = $oStream->getStreamOptions();
|
||||
if (!$bVerifyPeer && array_key_exists('ssl', $aOptions)) {
|
||||
// Disable verification
|
||||
$aOptions['ssl']['verify_peer'] = false;
|
||||
$aOptions['ssl']['verify_peer_name'] = false;
|
||||
$aOptions['ssl']['allow_self_signed'] = true;
|
||||
}
|
||||
$oStream->setStreamOptions($aOptions);
|
||||
$oTransport = $this->CreateSmtpTransport($sDsn, $bVerifyPeer);
|
||||
|
||||
$oMailer = new Mailer($oTransport);
|
||||
break;
|
||||
@@ -260,6 +251,36 @@ class EMailSymfony extends Email
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and configure an SMTP transport from a DSN string.
|
||||
*
|
||||
* Extracted from {@see SendSynchronous} to make SSL option handling independently testable.
|
||||
* When $bVerifyPeer is false, the ssl stream context options must be written unconditionally:
|
||||
* with STARTTLS the connection starts unencrypted, so the 'ssl' key is absent from the stream
|
||||
* options at construction time and only used later when stream_socket_enable_crypto() is called.
|
||||
*
|
||||
* @param string $sDsn Full Symfony Mailer DSN (smtp:// or smtps://)
|
||||
* @param bool $bVerifyPeer Whether to verify the peer SSL certificate
|
||||
*
|
||||
* @return \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
|
||||
*/
|
||||
protected function CreateSmtpTransport(string $sDsn, bool $bVerifyPeer): EsmtpTransport
|
||||
{
|
||||
/** @var EsmtpTransport $oTransport */
|
||||
$oTransport = Transport::fromDsn($sDsn);
|
||||
|
||||
$oStream = $oTransport->getStream();
|
||||
$aOptions = $oStream->getStreamOptions();
|
||||
if (!$bVerifyPeer) {
|
||||
$aOptions['ssl']['verify_peer'] = false;
|
||||
$aOptions['ssl']['verify_peer_name'] = false;
|
||||
$aOptions['ssl']['allow_self_signed'] = true;
|
||||
}
|
||||
$oStream->setStreamOptions($aOptions);
|
||||
|
||||
return $oTransport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reprocess the body of the message (if it is an HTML message)
|
||||
* to replace the URL of images based on attachments by a link
|
||||
@@ -416,13 +437,13 @@ class EMailSymfony extends Email
|
||||
|
||||
$this->m_aData['body'] = ['body' => $sBody, 'mimeType' => $sMimeType];
|
||||
|
||||
$oTextPart = new TextPart(strip_tags($sBody), 'utf-8', 'plain', 'base64');
|
||||
|
||||
// Embed inline images and store them in attachments (so BuildSymfonyMessageFromInternal can pick them)
|
||||
if ($sPrimaryMimeType === 'text/html') {
|
||||
$aAdditionalParts = $this->EmbedInlineImages($sBody);
|
||||
$oTextPart = new TextPart((new DefaultHtmlToTextConverter())->convert($sBody, 'utf-8'), 'utf-8', 'plain', 'base64');
|
||||
$oHtmlPart = new TextPart($sBody, 'utf-8', 'html', 'base64');
|
||||
$oAlternativePart = new AlternativePart($oHtmlPart, $oTextPart);
|
||||
// It's important de order parts from least prefered to most prefered as per RFC 2046 {@see https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.4}
|
||||
$oAlternativePart = new AlternativePart($oTextPart, $oHtmlPart);
|
||||
// Default root part is the HTML body
|
||||
$oRootPart = $oAlternativePart;
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Core\Email\EMailSymfony;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
|
||||
use Symfony\Component\Mime\Part\DataPart;
|
||||
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
|
||||
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
|
||||
use Symfony\Component\Mime\Part\TextPart;
|
||||
|
||||
class EmailSymfonyTest extends ItopTestCase
|
||||
{
|
||||
@@ -135,4 +141,221 @@ HTML;
|
||||
|
||||
$this->assertSame($sExpectedBody, $sActualBody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parts of the AlternativePart produced by SetBody() for an HTML email.
|
||||
*
|
||||
* Handles both the simple case (AlternativePart at root) and the inline-images case
|
||||
* where the root is a RelatedPart whose first child is the AlternativePart.
|
||||
*
|
||||
* @return AbstractPart[]
|
||||
*/
|
||||
private function GetAlternativePartsFromHtmlEmail(EMailSymfony $oEmail): array
|
||||
{
|
||||
$oSymfonyMessage = $this->GetNonPublicProperty($oEmail, 'm_oMessage');
|
||||
$oBody = $oSymfonyMessage->getBody();
|
||||
|
||||
// With inline images the root is a RelatedPart; the AlternativePart is its first child.
|
||||
if ($oBody instanceof RelatedPart) {
|
||||
$oBody = $oBody->getParts()[0];
|
||||
}
|
||||
|
||||
$this->assertInstanceOf(AlternativePart::class, $oBody, 'Body should be a multipart/alternative for HTML emails');
|
||||
|
||||
return $oBody->getParts();
|
||||
}
|
||||
|
||||
/**
|
||||
* RFC 2046 §5.1.4: parts in multipart/alternative must be ordered from least to most preferred.
|
||||
* Email clients display the last part they support, so text/plain must come first and text/html last.
|
||||
*
|
||||
* @see https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.4
|
||||
* @covers \Combodo\iTop\Core\Email\EmailSymfony::SetBody()
|
||||
* @since N°9574
|
||||
*/
|
||||
public function testSetBodyAlternativePartOrderForHtmlEmailIsPlainThenHtml(): void
|
||||
{
|
||||
$oEmail = new EMailSymfony();
|
||||
$oEmail->SetBody('<p>Hello there!</p>', 'text/html');
|
||||
|
||||
[$oFirstPart, $oSecondPart] = $this->GetAlternativePartsFromHtmlEmail($oEmail);
|
||||
|
||||
$this->assertSame('plain', $oFirstPart->getMediaSubtype(), 'First part must be text/plain (least preferred per RFC 2046)');
|
||||
$this->assertSame('html', $oSecondPart->getMediaSubtype(), 'Last part must be text/html (most preferred per RFC 2046)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideSetBodyPlainTextDoesNotContainCss
|
||||
*
|
||||
* @covers \Combodo\iTop\Core\Email\EmailSymfony::SetBody()
|
||||
* @since N°9574
|
||||
*/
|
||||
public function testSetBodyPlainTextDoesNotContainCss(string $sHtml, ?string $sCustomStyles): void
|
||||
{
|
||||
$oEmail = new EMailSymfony();
|
||||
$oEmail->SetBody($sHtml, 'text/html', $sCustomStyles);
|
||||
|
||||
// We locate the plain text part by subtype to be order-agnostic and isolate this assertion from the order bug.
|
||||
$aParts = $this->GetAlternativePartsFromHtmlEmail($oEmail);
|
||||
$oPlainPart = null;
|
||||
foreach ($aParts as $oPart) {
|
||||
if ($oPart instanceof TextPart && $oPart->getMediaSubtype() === 'plain') {
|
||||
$oPlainPart = $oPart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertNotNull($oPlainPart, 'No text/plain part found in the message');
|
||||
|
||||
$sPlainText = $oPlainPart->getBody();
|
||||
|
||||
$this->assertStringNotContainsString('<style>', $sPlainText, 'Style tag must not appear in plain text');
|
||||
$this->assertStringNotContainsString('color:', $sPlainText, 'CSS color rule must not appear in plain text');
|
||||
$this->assertStringNotContainsString('font-size:', $sPlainText, 'CSS font-size rule must not appear in plain text');
|
||||
$this->assertStringNotContainsString('@media', $sPlainText, 'CSS @media rule must not appear in plain text');
|
||||
$this->assertStringContainsString('Hello there!', $sPlainText, 'Actual content must be preserved in plain text');
|
||||
}
|
||||
|
||||
/**
|
||||
* The HTML part must contain the body content and the CSS inlined by Emogrifier.
|
||||
* This guards against regressions where the wrong body (e.g. the plain-text version)
|
||||
* would end up in the HTML part.
|
||||
*
|
||||
* @covers \Combodo\iTop\Core\Email\EmailSymfony::SetBody()
|
||||
* @since N°9574
|
||||
*/
|
||||
public function testSetBodyHtmlPartContainsBodyAndInlinedCss(): void
|
||||
{
|
||||
$oEmail = new EMailSymfony();
|
||||
$oEmail->SetBody('<html><body><p>Hello there!</p></body></html>', 'text/html', 'p { color: red; }');
|
||||
|
||||
$aParts = $this->GetAlternativePartsFromHtmlEmail($oEmail);
|
||||
|
||||
$oHtmlPart = null;
|
||||
foreach ($aParts as $oPart) {
|
||||
if ($oPart instanceof TextPart && $oPart->getMediaSubtype() === 'html') {
|
||||
$oHtmlPart = $oPart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertNotNull($oHtmlPart, 'No text/html part found in the message');
|
||||
|
||||
$sHtmlContent = $oHtmlPart->getBody();
|
||||
$this->assertStringContainsString('Hello there!', $sHtmlContent, 'HTML part must preserve the original text content');
|
||||
$this->assertStringContainsString('color: red', $sHtmlContent, 'HTML part must contain the CSS inlined by Emogrifier');
|
||||
}
|
||||
|
||||
/**
|
||||
* With inline images, SetBody() wraps the AlternativePart in a RelatedPart.
|
||||
* The AlternativePart must still be correctly ordered (plain first, HTML last)
|
||||
* and the plain-text part must not contain CSS.
|
||||
*
|
||||
* @see https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.4
|
||||
* @covers \Combodo\iTop\Core\Email\EmailSymfony::SetBody()
|
||||
* @since N°9574
|
||||
*/
|
||||
public function testSetBodyWithInlineImagesHasCorrectPartStructure(): void
|
||||
{
|
||||
// Anonymous subclass so we can inject a fake inline image part without a real inline image in DB
|
||||
$oEmail = new class () extends EMailSymfony {
|
||||
protected function EmbedInlineImages(string &$sBody): array
|
||||
{
|
||||
return [new DataPart('fake-image-data', 'image.png', 'image/png')];
|
||||
}
|
||||
};
|
||||
$oEmail->SetBody('<html><head><style>p { color: red; }</style></head><body><p>Hello there!</p></body></html>', 'text/html');
|
||||
|
||||
$oSymfonyMessage = $this->GetNonPublicProperty($oEmail, 'm_oMessage');
|
||||
$oBody = $oSymfonyMessage->getBody();
|
||||
|
||||
// Root must be a RelatedPart when inline images are present
|
||||
$this->assertInstanceOf(RelatedPart::class, $oBody, 'Root part must be multipart/related when inline images are present');
|
||||
|
||||
// The AlternativePart must be the first child of the RelatedPart
|
||||
$aRelatedParts = $oBody->getParts();
|
||||
$this->assertInstanceOf(AlternativePart::class, $aRelatedParts[0], 'First child of RelatedPart must be the AlternativePart');
|
||||
|
||||
// Order and CSS checks are delegated to the shared helper, which now handles RelatedPart
|
||||
[$oFirstPart, $oSecondPart] = $this->GetAlternativePartsFromHtmlEmail($oEmail);
|
||||
$this->assertSame('plain', $oFirstPart->getMediaSubtype(), 'First part must be text/plain (least preferred per RFC 2046)');
|
||||
$this->assertSame('html', $oSecondPart->getMediaSubtype(), 'Last part must be text/html (most preferred per RFC 2046)');
|
||||
}
|
||||
|
||||
public function provideSetBodyPlainTextDoesNotContainCss(): array
|
||||
{
|
||||
$sCustomStyles = 'p { color: blue; font-size: 14px; }';
|
||||
|
||||
return [
|
||||
'<style> tag in HTML, no custom styles' => [
|
||||
'<html><head><style>body { color: red; font-size: 12px; } @media print { p { color: black; } }</style></head><body><p>Hello there!</p></body></html>',
|
||||
null,
|
||||
],
|
||||
'<style> tag in HTML with custom styles' => [
|
||||
'<html><head><style>body { color: red; font-size: 12px; } @media print { p { color: black; } }</style></head><body><p>Hello there!</p></body></html>',
|
||||
$sCustomStyles,
|
||||
],
|
||||
'custom styles only, no <style> tag' => [
|
||||
'<html><body><p>Hello there!</p></body></html>',
|
||||
$sCustomStyles,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideCreateSmtpTransportSslOptions
|
||||
*/
|
||||
public function testCreateSmtpTransportSslOptions(string $sDsn, bool $bVerifyPeer, array $aExpectedSslOptions): void
|
||||
{
|
||||
$oEmail = new EMailSymfony();
|
||||
/** @var EsmtpTransport $oTransport */
|
||||
$oTransport = $this->InvokeNonPublicMethod(EMailSymfony::class, 'CreateSmtpTransport', $oEmail, [$sDsn, $bVerifyPeer]);
|
||||
|
||||
$aActualSslOptions = $oTransport->getStream()->getStreamOptions()['ssl'] ?? [];
|
||||
|
||||
$this->assertSame($aExpectedSslOptions, $aActualSslOptions);
|
||||
}
|
||||
|
||||
public function provideCreateSmtpTransportSslOptions(): array
|
||||
{
|
||||
$aDisabledVerification = [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true,
|
||||
];
|
||||
|
||||
return [
|
||||
// Regression scenario (N°9584): STARTTLS starts the connection unencrypted, so the 'ssl' key
|
||||
// is absent from stream options at construction time. verify_peer=false must still be applied.
|
||||
'STARTTLS, verify_peer=false' => [
|
||||
'smtp://localhost:587?encryption=starttls',
|
||||
false,
|
||||
$aDisabledVerification,
|
||||
],
|
||||
'implicit TLS (smtps), verify_peer=false' => [
|
||||
'smtps://localhost:465',
|
||||
false,
|
||||
$aDisabledVerification,
|
||||
],
|
||||
'plain SMTP, verify_peer=false' => [
|
||||
'smtp://localhost:25',
|
||||
false,
|
||||
$aDisabledVerification,
|
||||
],
|
||||
// Default behavior: verify_peer=true must leave stream options untouched (empty).
|
||||
'STARTTLS, verify_peer=true (default)' => [
|
||||
'smtp://localhost:587?encryption=starttls',
|
||||
true,
|
||||
[],
|
||||
],
|
||||
'implicit TLS (smtps), verify_peer=true (default)' => [
|
||||
'smtps://localhost:465',
|
||||
true,
|
||||
[],
|
||||
],
|
||||
'plain SMTP, verify_peer=true (default)' => [
|
||||
'smtp://localhost:25',
|
||||
true,
|
||||
[],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user