<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
  <classes>
    <class id="BackgroundTaskEx" _delta="define">
      <parent>DBObject</parent>
      <properties>
        <category/>
        <abstract>true</abstract>
        <db_table>priv_background_task_ex</db_table>
        <naming>
          <attributes>
            <attribute id="name"/>
          </attributes>
        </naming>
      </properties>
      <fields>
        <field id="name" xsi:type="AttributeString">
          <sql>name</sql>
          <default_value/>
          <is_null_allowed>false</is_null_allowed>
          <tracking_level>none</tracking_level>
        </field>
        <field id="current_action_id" xsi:type="AttributeExternalKey">
          <sql>current_action_id</sql>
          <target_class>BackgroundTaskExAction</target_class>
          <is_null_allowed>true</is_null_allowed>
          <tracking_level>none</tracking_level>
          <on_target_delete>DEL_MANUAL</on_target_delete>
        </field>
        <field id="message" xsi:type="AttributeText">
          <sql>message</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
          <tracking_level>none</tracking_level>
        </field>
        <field id="status" xsi:type="AttributeEnum">
          <sql>status</sql>
          <is_null_allowed>false</is_null_allowed>
          <default_value>created</default_value>
          <tracking_level>none</tracking_level>
          <sort_type>rank</sort_type>
          <values>
            <value id="created">
              <code>created</code>
              <rank>1</rank>
            </value>
            <value id="starting">
              <code>starting</code>
              <rank>2</rank>
            </value>
            <value id="running">
              <code>running</code>
              <rank>3</rank>
            </value>
            <value id="recovering">
              <code>recovering</code>
              <rank>4</rank>
            </value>
            <value id="paused">
              <code>paused</code>
              <rank>5</rank>
            </value>
          </values>
        </field>
        <field id="type" xsi:type="AttributeEnum">
          <sql>type</sql>
          <is_null_allowed>false</is_null_allowed>
          <default_value>cron</default_value>
          <tracking_level>none</tracking_level>
          <values>
            <value id="cron">
              <code>cron</code>
            </value>
            <value id="interactive">
              <code>interactive</code>
            </value>
          </values>
        </field>
      </fields>
      <methods>
        <method id="GetCurrentAction">
          <static>false</static>
          <access>public</access>
          <type>Overload-ExNihilo</type>
          <code><![CDATA[
       public function GetCurrentAction()
       {
            $sCurrentActionId = $this->Get('current_action_id');
            if ($sCurrentActionId) {
                return MetaModel::GetObject('BackgroundTaskExAction', $sCurrentActionId, false);
            }
            return null;
       }
]]></code>
        </method>
        <method id="GetNextAction">
          <static>false</static>
          <access>public</access>
          <type>Overload-ExNihilo</type>
          <code><![CDATA[
       public function GetNextAction()
       {
            $sId = $this->GetKey();
            $oSet = new DBObjectSet(DBSearch::FromOQL("SELECT BackgroundTaskExAction WHERE task_id=:id"), ['rank' => true], ['id' => $sId]);
            $oSet->SetLimit(1);
            $oAction = $oSet->Fetch();
            $oActionId = is_null($oAction) ? null : $oAction->GetKey();
            $this->Set('current_action_id', $oActionId);
            $this->DBUpdate();
            return $oAction;
       }
]]></code>
        </method>
      </methods>
      <presentation>
        <list>
          <items>
            <item id="name">
              <rank>10</rank>
            </item>
            <item id="status">
              <rank>60</rank>
            </item>
          </items>
        </list>
      </presentation>
    </class>
    <class id="BackgroundTaskExAction" _delta="define">
      <parent>DBObject</parent>
      <php_parent>
        <name>AbstractBackgroundTaskExAction</name>
      </php_parent>
      <properties>
        <category/>
        <abstract>true</abstract>
        <db_table>priv_background_task_ex_action</db_table>
        <naming>
          <attributes>
            <attribute id="name"/>
          </attributes>
        </naming>
      </properties>
      <fields>
        <field id="name" xsi:type="AttributeString">
          <sql>name</sql>
          <default_value/>
          <is_null_allowed>false</is_null_allowed>
          <tracking_level>none</tracking_level>
        </field>
        <field id="rank" xsi:type="AttributeInteger">
          <sql>rank</sql>
          <default_value>1</default_value>
          <is_null_allowed>false</is_null_allowed>
          <tracking_level>none</tracking_level>
        </field>
        <field id="task_id" xsi:type="AttributeExternalKey">
          <sql>task_id</sql>
          <target_class>BackgroundTaskEx</target_class>
          <is_null_allowed>false</is_null_allowed>
          <tracking_level>none</tracking_level>
          <on_target_delete>DEL_AUTO</on_target_delete>
        </field>
      </fields>
      <methods>
        <method id="InitActionParams">
          <static>false</static>
          <access>public</access>
          <type>Overload-ExNihilo</type>
          <comment>
            /**
            * Initialize the action and save specific data
            * @return bool true if action can continue
            */
          </comment>
          <code><![CDATA[
       public function InitActionParams(): bool
       {
       					return true;
       }
]]></code>
        </method>
        <method id="ChangeActionParamsOnError">
          <static>false</static>
          <access>public</access>
          <type>Overload-ExNihilo</type>
          <comment>
            /**
            * Change the specific data to retry the action on error
            * @return bool true if action can continue
            */
          </comment>
          <code><![CDATA[
       public function ChangeActionParamsOnError(): bool
       {
					return true;
       }
]]></code>
        </method>
        <method id="ExecuteAction">
          <static>false</static>
          <access>public</access>
          <type>Overload-ExNihilo</type>
          <comment>
            /**
            * Execute the action using the specific data
            * When execution stops after execution timeout, store the parameters for the next execution in the $oTask object.
            *
            * @param int iEndExecutionTime Unix timestamp of the end of execution
            * @return bool true when action is finished, false if paused on execution timeout
            */
          </comment>
          <code><![CDATA[
       public function ExecuteAction($iEndExecutionTime)
       {
            return true;
       }
]]></code>
        </method>
      </methods>
      <presentation>
        <list>
          <items>
            <item id="name">
              <rank>10</rank>
            </item>
            <item id="rank">
              <rank>60</rank>
            </item>
          </items>
        </list>
      </presentation>
    </class>
    <class id="DatabaseProcessRule" _delta="define">
      <parent>cmdbAbstractObject</parent>
      <properties>
        <category>bizmodel,searchable</category>
        <abstract>true</abstract>
        <db_table>database_process_rule</db_table>
        <naming>
          <attributes>
            <attribute id="name"/>
          </attributes>
        </naming>
        <reconciliation>
          <attributes>
            <attribute id="target_class"/>
          </attributes>
        </reconciliation>
      </properties>
      <fields>
        <field id="target_class" xsi:type="AttributeString">
          <sql>target_class</sql>
          <default_value/>
          <is_null_allowed>false</is_null_allowed>
        </field>
        <field id="name" xsi:type="AttributeString">
          <sql>name</sql>
          <default_value/>
          <is_null_allowed>false</is_null_allowed>
        </field>
        <field id="status" xsi:type="AttributeEnum">
          <values>
            <value id="active">
                <code>active</code>
            </value>
            <value id="inactive">
                <code>inactive</code>
            </value>
          </values>
          <sql>status</sql>
          <default_value>active</default_value>
          <is_null_allowed>false</is_null_allowed>
          <display_style>list</display_style>
        </field>
        <field id="type" xsi:type="AttributeEnum">
          <values>
            <value id="simple">
                <code>simple</code>
            </value>
            <value id="advanced">
                <code>advanced</code>
            </value>
          </values>
          <dependencies>
            <attribute id="date_to_check_att"/>
            <attribute id="retention_delay"/>
            <attribute id="oql_scope"/>
          </dependencies>
          <sql>type</sql>
          <default_value>simple</default_value>
          <is_null_allowed>false</is_null_allowed>
        </field>
        <field id="date_to_check_att" xsi:type="AttributeString">
          <sql>date_to_check_att</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
        </field>
        <field id="retention_delay" xsi:type="AttributeInteger">
          <sql>retention_delay</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
        </field>
        <field id="oql_scope" xsi:type="AttributeOQL">
          <sql>oql_scope</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
        </field>
      </fields>
      <methods>
        <method id="GetInitialStateAttributeFlags">
          <static>false</static>
          <access>public</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[	public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = array())
	{
		if ($sAttCode == 'type') {
		    return OPT_ATT_READONLY;
		}
		return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
	}
]]></code>
        </method>
        <method id="GetAttributeFlags">
          <static>false</static>
          <access>public</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[	public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
	{
		if ($sAttCode == 'type') {
		    return OPT_ATT_READONLY;
		}
		return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
	}
]]></code>
        </method>
        <method id="ComputeValues">
          <static>false</static>
          <access>public</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[	public function ComputeValues()
	{
		// Compute the type of the rule
		$oScopeAttDef = MetaModel::GetAttributeDef(get_class($this), 'oql_scope');
		$sType = ($oScopeAttDef->IsNull($this->Get('oql_scope'))) ? 'simple' : 'advanced';
		$this->Set('type', $sType);

		return parent::ComputeValues();
	}]]></code>
        </method>
        <method id="DoCheckToWrite">
          <static>false</static>
          <access>public</access>
          <code><![CDATA[    	public function DoCheckToWrite()
	{
		parent::DoCheckToWrite();

		// Checking class / attributes consistency with Datamodel
		$sClass = $this->Get('target_class');
		$sDateToCheckAttCode = $this->Get('date_to_check_att');
		$sOqlScope = $this->Get('oql_scope');
		// - Class
		if (!MetaModel::IsValidClass($sClass)) {
			$this->m_aCheckIssues[] = Dict::Format('Class:DatabaseProcessRule/Error:ClassNotValid', $sClass);

			return;
		}
		// - Date to check attribute
		if (!empty($sDateToCheckAttCode)) {
			if (!MetaModel::IsValidAttCode($sClass, $sDateToCheckAttCode)) {
				$this->m_aCheckIssues[] = Dict::Format('Class:DatabaseProcessRule/Error:AttributeNotValid', $sClass, $sDateToCheckAttCode);
			} else {
				$oAttDef = MetaModel::GetAttributeDef($sClass, $sDateToCheckAttCode);
				if (($oAttDef instanceof AttributeDateTime) === false) {
					$oAttDate = MetaModel::GetAttributeDef('DatabaseProcessRule', 'date_to_check_att');
					$this->m_aCheckIssues[] = Dict::Format('Class:DatabaseProcessRule/Error:AttributeMustBeDate', $sClass, $sDateToCheckAttCode, $oAttDate->GetLabel());
				}
			}
		}

		// Checking option consistency
		// - At least one option must be filled (either simple or advanced)
		$bNoOptionFilled = true;
		$aOptionAttCodes = array('date_to_check_att', 'retention_delay', 'oql_scope');
		foreach ($aOptionAttCodes as $sOptionAttCode) {
			$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sOptionAttCode);
			$value = $this->Get($sOptionAttCode);
			if (!$oAttDef->IsNull($value)) {
				$bNoOptionFilled = false;
				break;
			}
		}

		if ($bNoOptionFilled) {
			$this->m_aCheckIssues[] = Dict::Format('Class:DatabaseProcessRule/Error:NoOptionFilled');
		} // - Checking that option 1 is valid if selected
		elseif (empty($sOqlScope)) {
			$bOptionOneValid = true;

			// Removing OQL attribute as we only test option 1 attributes
			array_pop($aOptionAttCodes);
			foreach ($aOptionAttCodes as $sOptionAttCode) {
				$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sOptionAttCode);
				$value = $this->Get($sOptionAttCode);
				if ($oAttDef->IsNull($value)) {
					$bOptionOneValid = false;
					break;
				}
			}

			if (!$bOptionOneValid) {
				$this->m_aCheckIssues[] = Dict::Format('Class:DatabaseProcessRule/Error:OptionOneMissingField');
			}
		} // - Checking that option 2 OQL is about the right class
		elseif (!empty($sOqlScope)) {
			try {
				$oSearch = DBObjectSearch::FromOQL($sOqlScope);
				$sOqlClass = $oSearch->GetClass();
				if ($sOqlClass !== $sClass) {
					$this->m_aCheckIssues[] = Dict::Format('Class:StateRule/Error:OQLClassDontMatch', $sClass, $sOqlClass);
				}
			} catch (Exception $e) {
				$this->m_aCheckIssues[] = Dict::Format('Class:StateRule/Error:OQLNotValid', $e->getMessage());
			}
		}
	}
]]></code>
        </method>
        <method id="GetFilter">
          <static>false</static>
          <access>public</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[		/**
	 * @return DBObjectSearch
	 * @throws \OQLException
	 */
	public function GetFilter()
	{
		if ($this->Get('type') === 'advanced') {
			$oSearch = DBObjectSearch::FromOQL($this->Get('oql_scope'));
		} else {
			$sClass = $this->Get('target_class');
			$sDateAttCode = $this->Get('date_to_check_att');
			$sOQL = 'SELECT '.$sClass.' WHERE ';
			$sOQL .= $sDateAttCode.' <= DATE_SUB(NOW(), INTERVAL :retention_delay DAY)';
			$oSearch = DBObjectSearch::FromOQL($sOQL);
			$oSearch->SetInternalParams(
				array(
					'retention_delay' => $this->Get('retention_delay'),
				)
			);
		}

		return $oSearch;
	}
]]></code>
        </method>
        <method id="DisplayBareRelations">
          <static>false</static>
          <access>public</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[		/**
	 * @param \WebPage $oPage
	 * @param bool $bEditMode
	 */
	public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
	{
		parent::DisplayBareRelations($oPage, $bEditMode);

		if (!$bEditMode) {
			$oPage->SetCurrentTab(Dict::S('UI:DatabaseProcessRule:Preview'));
			$this->OnShowPreview($oPage);
		}
	}]]></code>
        </method>
        <method id="OnShowPreview">
          <static>false</static>
          <access>protected</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[	/**
	 * @param \WebPage $oPage
	 *
	 * @throws \ArchivedObjectException
	 * @throws \CoreException
	 * @throws \DictExceptionMissingString
	 */
	public function OnShowPreview(WebPage $oPage)
	{
		$sClass = $this->Get('target_class');

		if (version_compare(ITOP_DESIGN_LATEST_VERSION, '3.0') < 0) {
			$oPage->p(MetaModel::GetClassIcon($sClass).'&nbsp;'.Dict::Format('UI:DatabaseProcessRule:Title', MetaModel::GetName($sClass)));
		} else {
			$oUiMedallionBlock = new Combodo\iTop\Application\UI\Base\Component\MedallionIcon\MedallionIcon(MetaModel::GetClassIcon($sClass, false));
			$oUiMedallionBlock->SetDescription(Dict::Format('UI:DatabaseProcessRule:Title', MetaModel::GetName($sClass)));
			$oPage->AddSubBlock($oUiMedallionBlock);
		};

		$aParams = array(
			'menu' => true,
			'table_id' => 'DatabaseProcessRule_preview_rule_'.$this->GetKey(),
		);
		$oBlock = new DisplayBlock($this->GetFilter(), 'list', true, $aParams);
		$oBlock->Display($oPage, 'rel_preview_rule_'.$this->GetKey(), $aParams);
	}]]></code>
        </method>
        <method id="OnExecution ">
          <static>true</static>
          <access>protected</access>
          <type>Overload-DBObject</type>
          <code><![CDATA[/**
	 * @param \WebPage $oPage
	 */
	public static function OnExecution ( $aIds)
	{
		//Default do nothing
	}]]></code>
        </method>
      </methods>
      <presentation>
        <list>
          <items>
            <item id="target_class">
              <rank>10</rank>
            </item>
            <item id="name">
              <rank>20</rank>
            </item>
            <item id="status">
              <rank>30</rank>
            </item>
            <item id="type">
              <rank>40</rank>
            </item>
          </items>
        </list>
        <search>
          <items>
            <item id="name">
              <rank>10</rank>
            </item>
            <item id="target_class">
              <rank>20</rank>
            </item>
            <item id="status">
              <rank>30</rank>
            </item>
            <item id="type">
              <rank>40</rank>
            </item>
            <item id="date_to_check_att">
              <rank>70</rank>
            </item>
            <item id="retention_delay">
              <rank>80</rank>
            </item>
            <item id="oql_scope">
              <rank>90</rank>
            </item>
          </items>
        </search>
        <details>
          <items>
            <item id="col:col0">
              <rank>10</rank>
              <items>
                <item id="fieldset:DatabaseProcessRule:general">
                  <rank>10</rank>
                  <items>
                    <item id="name">
                      <rank>10</rank>
                    </item>
                    <item id="target_class">
                      <rank>20</rank>
                    </item>
                    <item id="status">
                      <rank>30</rank>
                    </item>
                    <item id="type">
                      <rank>40</rank>
                    </item>
                  </items>
                </item>
              </items>
            </item>
            <item id="col:col1">
              <rank>20</rank>
              <items>
                <item id="fieldset:DatabaseProcessRule:simple">
                  <rank>10</rank>
                  <items>
                    <item id="date_to_check_att">
                      <rank>30</rank>
                    </item>
                    <item id="retention_delay">
                      <rank>40</rank>
                    </item>
                  </items>
                </item>
              </items>
            </item>
            <item id="col:col2">
              <rank>30</rank>
              <items>
                <item id="fieldset:DatabaseProcessRule:advanced">
                  <rank>100</rank>
                  <items>
                    <item id="oql_scope">
                      <rank>10</rank>
                    </item>
                  </items>
                </item>
              </items>
            </item>
          </items>
        </details>
      </presentation>
    </class>
  </classes>
  <module_parameters>
    <parameters id="combodo-complex-background-task" _delta="define">
      <time>01:00</time>
      <end_time>23:30</end_time>
      <max_execution_time>30</max_execution_time>
      <week_days>sunday</week_days>
    </parameters>
  </module_parameters>
</itop_design>
