Можно попробовать более простой вариант. Если автоматический анализ влияние и привязка КЕ не нужны, их можно попробовать отключить.
В вашем модуле с классом RoutineChange переопределите methods, скопировав содержимое из класса Сhange, но удалив из OnInsert() и из OnUpdate() вызов UpdateImpactedItems().
В методах класса Ticket, представлены два метода DBInsertNo Reload и MakeTicketRef, я не вижу здесь что-то подобное формированию перечня линков lnkFunctionalCIToTicket.
я скопировал весь класс Ticket в свой модуль, и сделал redefine всему блоку methods, и на этом остановился
Перестаньте копировать всё подряд. В свой модуль вносите только изменения относительно стандартной модели данных.
Код метода тут UpdateImpactedItems(): main.itop-tickets.php.
Класс Ticket тут: datamodel.itop-tickets.xml.
В своем модуле для класса Ticket аналогично представленным в нём методам делаете новый метод UpdateImpactedItems, куда вставляете код из main.itop-tickets.php. Затем этот код редактируете.
Сократил код. Определил новый метод:
<class id="Ticket">
<fields>
<field id="description" xsi:type="AttributeText" _delta="redefine">
<sql>description</sql>
<default_value/>
<is_null_allowed>true</is_null_allowed>
</field>
</fields>
<methods>
<method id="UpdateImpactedItems" _delta="define">
</method>
</methods>
</class>
Теперь между тэгами методам, нужно вставить весь код?:
public function UpdateImpactedItems()
{
require_once(APPROOT.'core/displayablegraph.class.inc.php');
$oContactsSet = $this->Get('contacts_list');
$oCIsSet = $this->Get('functionalcis_list');
$aCIsToImpactCode = array();
$aSources = array();
$aExcluded = array();
$oCIsSet->Rewind();
while ($oLink = $oCIsSet->Fetch())
{
$iKey = $oLink->Get('functionalci_id');
$aCIsToImpactCode[$iKey] = $oLink->Get('impact_code');
if ($oLink->Get('impact_code') == 'manual')
{
$oObj = MetaModel::GetObject('FunctionalCI', $iKey);
$aSources[$iKey] = $oObj;
}
else if ($oLink->Get('impact_code') == 'not_impacted')
{
$oObj = MetaModel::GetObject('FunctionalCI', $iKey);
$aExcluded[$iKey] = $oObj;
}
}
$aContactsToRoleCode = array();
$oContactsSet->Rewind();
while ($oLink = $oContactsSet->Fetch())
{
$iKey = $oLink->Get('contact_id');
$aContactsToRoleCode[$iKey] = $oLink->Get('role_code');
if ($oLink->Get('role_code') == 'do_not_notify')
{
$oObj = MetaModel::GetObject('Contact', $iKey);
$aExcluded[$iKey] = $oObj;
}
}
$oNewCIsSet = DBObjectSet::FromScratch('lnkFunctionalCIToTicket');
foreach($aCIsToImpactCode as $iKey => $sImpactCode)
{
if ($sImpactCode != 'computed')
{
$oNewLink = new lnkFunctionalCIToTicket();
$oNewLink->Set('functionalci_id', $iKey);
$oNewLink->Set('impact_code', $sImpactCode);
$oNewCIsSet->AddObject($oNewLink);
}
}
$oNewContactsSet = DBObjectSet::FromScratch('lnkContactToTicket');
foreach($aContactsToRoleCode as $iKey => $sImpactCode)
{
if ($sImpactCode != 'computed')
{
$oNewLink = new lnkContactToTicket();
$oNewLink->Set('contact_id', $iKey);
$oNewLink->Set('role_code', $sImpactCode);
$oNewContactsSet->AddObject($oNewLink);
}
}
$oContactsSet = DBObjectSet::FromScratch('lnkContactToTicket');
$sContextKey = 'itop-tickets/relation_context/'.get_class($this).'/impacts/down';
$aContextDefs = DisplayableGraph::GetContextDefinitions($sContextKey, true, array('this' => $this));
$aDefaultContexts = array();
foreach($aContextDefs as $sKey => $aDefinition)
{
// Add the default context queries to the computation
if (array_key_exists('default', $aDefinition) && ($aDefinition['default'] == 'yes'))
{
$aDefaultContexts[] = $aDefinition['oql'];
}
}
// Merge the directly impacted items with the "new" ones added by the "context" queries
$aGraphObjects = array();
$oRawGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true /* bEnableRedundancy */, $aExcluded);
$oIterator = new RelationTypeIterator($oRawGraph, 'Node');
foreach ($oIterator as $oNode)
{
// Any object node reached AND different from a source will do
if ( ($oNode instanceof RelationObjectNode) && ($oNode->GetProperty('is_reached')) && (!$oNode->GetProperty('source')) )
{
$oObj = $oNode->GetProperty('object');
$iKey = $oObj->GetKey();
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
$aGraphObjects[get_class($oObj).'::'.$iKey] = $oNode->GetProperty('object');
}
}
if (count($aDefaultContexts) > 0)
{
$oAnnotatedGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true /* bEnableRedundancy */, $aExcluded, $aDefaultContexts);
$oIterator = new RelationTypeIterator($oAnnotatedGraph, 'Node');
foreach ($oIterator as $oNode)
{
// Only pick the nodes which are NOT impacted by a context root cause, and merge them in the list
if ( ($oNode instanceof RelationObjectNode) && ($oNode->GetProperty('is_reached')) && (!$oNode->GetProperty('source')) && ($oNode->GetProperty('context_root_causes', null) == null) )
{
$oObj = $oNode->GetProperty('object');
$iKey = $oObj->GetKey();
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
$aGraphObjects[get_class($oObj).'::'.$iKey] = $oNode->GetProperty('object');
}
}
}
foreach ($aGraphObjects as $oObj)
{
$iKey = $oObj->GetKey();
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
switch ($sRootClass)
{
case 'FunctionalCI':
// Only link FunctionalCIs which are not already linked to the ticket
if (!array_key_exists($iKey, $aCIsToImpactCode) || ($aCIsToImpactCode[$iKey] != 'not_impacted'))
{
$oNewLink = new lnkFunctionalCIToTicket();
$oNewLink->Set('functionalci_id', $iKey);
$oNewLink->Set('impact_code', 'computed');
$oNewCIsSet->AddObject($oNewLink);
}
break;
case 'Contact':
// Only link Contacts which are not already linked to the ticket
if (!array_key_exists($iKey, $aContactsToRoleCode) || ($aCIsToImpactCode[$iKey] != 'do_not_notify'))
{
$oNewLink = new lnkContactToTicket();
$oNewLink->Set('contact_id', $iKey);
$oNewLink->Set('role_code', 'computed');
$oNewContactsSet->AddObject($oNewLink);
}
break;
}
}
$this->Set('functionalcis_list', $oNewCIsSet);
$this->Set('contacts_list', $oNewContactsSet);
}
Как в нем правильно определить значения поля action_code?
Да, только посмотрите, как оформлены методы в стандартных моделях.
Нужно разобрать как работает код, а потом куда-то воткнуть что-то типа $oNewLink->Set('action_code', $sActionCode);
, где переменная $sActionCode
должна содержать одно из ваших значений.
После того, как я определил новый метод, и вставил в него весь код из main, toolkit выдает вот такое сообщение:
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:154 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:154 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:164 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:164 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:164 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:164 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:179 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:179 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:179 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:179 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:179 Message:xmlParseEntityRef: no name
File: /var/www/itop/TEST/extensions/action-ticket/datamodel.action-ticket.xml Line:179 Message:xmlParseEntityRef: no name
Но пишет что все ОК - Это нормально?
@vladimir помогите пожалуйста разобраться с кодом, я его не понимаю(…я вставил $oNewLink->Set(‘action_code’, $sActionCode); во все условия этой функции, но безрезультатно
igsao10:
Это нормально?
Нет.
ЧТобы разобраться с кодом, нужно немного разобраться с php. iTop заканчивается на xml-модели данных.
Вот ваш метод:
<method id="UpdateImpactedItems" _delta="define">
<static>false</static>
<access>protected</access>
<type>Overload-DBObject</type>
<code><![CDATA[public function UpdateImpactedItems()
{
require_once(APPROOT.'core/displayablegraph.class.inc.php');
$oContactsSet = $this->Get('contacts_list');
$oCIsSet = $this->Get('functionalcis_list');
$aCIsToImpactCode = array();
$aSources = array();
$aExcluded = array();
$oCIsSet->Rewind();
while ($oLink = $oCIsSet->Fetch())
{
$iKey = $oLink->Get('functionalci_id');
$aCIsToImpactCode[$iKey] = $oLink->Get('impact_code');
$aCIsToActionCode[$iKey] = $oLink->Get('action_code');
if ($oLink->Get('impact_code') == 'manual')
{
$oObj = MetaModel::GetObject('FunctionalCI', $iKey);
$aSources[$iKey] = $oObj;
}
else if ($oLink->Get('impact_code') == 'not_impacted')
{
$oObj = MetaModel::GetObject('FunctionalCI', $iKey);
$aExcluded[$iKey] = $oObj;
}
}
$aContactsToRoleCode = array();
$oContactsSet->Rewind();
while ($oLink = $oContactsSet->Fetch())
{
$iKey = $oLink->Get('contact_id');
$aContactsToRoleCode[$iKey] = $oLink->Get('role_code');
if ($oLink->Get('role_code') == 'do_not_notify')
{
$oObj = MetaModel::GetObject('Contact', $iKey);
$aExcluded[$iKey] = $oObj;
}
}
$oNewCIsSet = DBObjectSet::FromScratch('lnkFunctionalCIToTicket');
foreach($aCIsToImpactCode as $iKey => $sImpactCode)
{
if ($sImpactCode != 'computed')
{
$oNewLink = new lnkFunctionalCIToTicket();
$oNewLink->Set('functionalci_id', $iKey);
$oNewLink->Set('impact_code', $sImpactCode);
$oNewLink->Set('action_code', $aCIsToActionCode[$iKey]);
$oNewCIsSet->AddObject($oNewLink);
}
}
$oNewContactsSet = DBObjectSet::FromScratch('lnkContactToTicket');
foreach($aContactsToRoleCode as $iKey => $sImpactCode)
{
if ($sImpactCode != 'computed')
{
$oNewLink = new lnkContactToTicket();
$oNewLink->Set('contact_id', $iKey);
$oNewLink->Set('role_code', $sImpactCode);
$oNewContactsSet->AddObject($oNewLink);
}
}
$oContactsSet = DBObjectSet::FromScratch('lnkContactToTicket');
$sContextKey = 'itop-tickets/relation_context/'.get_class($this).'/impacts/down';
$aContextDefs = DisplayableGraph::GetContextDefinitions($sContextKey, true, array('this' => $this));
$aDefaultContexts = array();
foreach($aContextDefs as $sKey => $aDefinition)
{
// Add the default context queries to the computation
if (array_key_exists('default', $aDefinition) && ($aDefinition['default'] == 'yes'))
{
$aDefaultContexts[] = $aDefinition['oql'];
}
}
// Merge the directly impacted items with the "new" ones added by the "context" queries
$aGraphObjects = array();
$oRawGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true /* bEnableRedundancy */, $aExcluded);
$oIterator = new RelationTypeIterator($oRawGraph, 'Node');
foreach ($oIterator as $oNode)
{
// Any object node reached AND different from a source will do
if ( ($oNode instanceof RelationObjectNode) && ($oNode->GetProperty('is_reached')) && (!$oNode->GetProperty('source')) )
{
$oObj = $oNode->GetProperty('object');
$iKey = $oObj->GetKey();
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
$aGraphObjects[get_class($oObj).'::'.$iKey] = $oNode->GetProperty('object');
}
}
if (count($aDefaultContexts) > 0)
{
$oAnnotatedGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true /* bEnableRedundancy */, $aExcluded, $aDefaultContexts);
$oIterator = new RelationTypeIterator($oAnnotatedGraph, 'Node');
foreach ($oIterator as $oNode)
{
// Only pick the nodes which are NOT impacted by a context root cause, and merge them in the list
if ( ($oNode instanceof RelationObjectNode) && ($oNode->GetProperty('is_reached')) && (!$oNode->GetProperty('source')) && ($oNode->GetProperty('context_root_causes', null) == null) )
{
$oObj = $oNode->GetProperty('object');
$iKey = $oObj->GetKey();
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
$aGraphObjects[get_class($oObj).'::'.$iKey] = $oNode->GetProperty('object');
}
}
}
foreach ($aGraphObjects as $oObj)
{
$iKey = $oObj->GetKey();
$sRootClass = MetaModel::GetRootClass(get_class($oObj));
switch ($sRootClass)
{
case 'FunctionalCI':
// Only link FunctionalCIs which are not already linked to the ticket
if (!array_key_exists($iKey, $aCIsToImpactCode) || ($aCIsToImpactCode[$iKey] != 'not_impacted'))
{
$oNewLink = new lnkFunctionalCIToTicket();
$oNewLink->Set('functionalci_id', $iKey);
$oNewLink->Set('impact_code', 'computed');
$oNewCIsSet->AddObject($oNewLink);
}
break;
case 'Contact':
// Only link Contacts which are not already linked to the ticket
if (!array_key_exists($iKey, $aContactsToRoleCode) || ($aCIsToImpactCode[$iKey] != 'do_not_notify'))
{
$oNewLink = new lnkContactToTicket();
$oNewLink->Set('contact_id', $iKey);
$oNewLink->Set('role_code', 'computed');
$oNewContactsSet->AddObject($oNewLink);
}
break;
}
}
$this->Set('functionalcis_list', $oNewCIsSet);
$this->Set('contacts_list', $oNewContactsSet);
}]]></code>
</method>
Ситуация с добавлением метода не изменилась, так и сбрасывается в “неопределен” (
Значит вы где-то ошиблись.
@vladimir Спасибо огромное! работает! оказывается дело в условие. если добавлен вручную, то применяется указанное действие, если нет, то выставляется неопределен…а я то думал…
осталось последнее действие - это добавить кнопку “создать КЕ” в форме поиска КЕ
подскажите пожалуйста в каком файле и как это сделать?
Во вкладке сохраняется то, что добавлено в ручную или не влияет . Остальное пересчитывается при сохранении тикета.
Быстро — никак. Нужно ковырять код.
Получилось вот так:
добавил
$sHtml .= "<p align=\"right\"><a href=\"UI.php?operation=new&class=FunctionalCI&c%5Bmenu%5D=NewCI\" target=\"_blank\">Create CI</a></p>\n";
в файл application/cmdbabstract.class.inc.php
Если вас это устраивает, то можно и так конечно)
Пока устраивает, главное что она есть
2 сообщений перенесены в уже существующую тему: Модуль “Управления Изменениями”
Rudd
22.Апрель.2016 08:09:19
99
Товарищи, чтоб создать простую форму “Создано-закрыто” или “создано-в работе-закрыто” для тикетов хелпдеска нужно тоже создавать свой модуль? или может есть готовый где ?
Если создавать свой, подскажите что копировать из itop-request-mgmt?