|
18 | 18 | */
|
19 | 19 |
|
20 | 20 | use Combodo\iTop\Application\WebPage\iTopWebPage;
|
| 21 | +use Combodo\iTop\Core\CMDBChange\CMDBChangeOrigin; |
21 | 22 |
|
22 | 23 | require_once('../approot.inc.php');
|
23 | 24 | require_once(APPROOT.'/application/application.inc.php');
|
24 | 25 |
|
25 | 26 | require_once(APPROOT.'/application/startup.inc.php');
|
26 | 27 | require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
27 |
| -LoginWebPage::DoLogin(); |
| 28 | +LoginWebPage::DoLogin(); |
28 | 29 |
|
29 | 30 | $sOperation = utils::ReadParam('operation', 'menu');
|
30 | 31 | $oAppContext = new ApplicationContext();
|
|
33 | 34 |
|
34 | 35 | // Main program
|
35 | 36 | $sOperation = utils::ReadParam('operation', 'details');
|
36 |
| -try |
| 37 | + |
| 38 | +/** |
| 39 | + * @param \DBObject|null $oReplica |
| 40 | + * @param $this |
| 41 | + * |
| 42 | + * @return \SynchroLog |
| 43 | + * @throws \ArchivedObjectException |
| 44 | + * @throws \CoreCannotSaveObjectException |
| 45 | + * @throws \CoreException |
| 46 | + * @throws \CoreUnexpectedValue |
| 47 | + * @throws \CoreWarning |
| 48 | + * @throws \MySQLException |
| 49 | + * @throws \OQLException |
| 50 | + * @throws \SynchroExceptionNotStarted |
| 51 | + */ |
| 52 | +function Synchro($oReplica): SynchroLog |
37 | 53 | {
|
38 |
| - switch($sOperation) |
39 |
| - { |
40 |
| - case 'details': |
41 |
| - $iId = utils::ReadParam('id', null); |
42 |
| - if ($iId == null) |
43 |
| - { |
44 |
| - throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id')); |
| 54 | + $oDataSource = MetaModel::GetObject('SynchroDataSource', $oReplica->Get('sync_source_id')); |
| 55 | + |
| 56 | + $oStatLog = new SynchroLog(); |
| 57 | + $oStatLog->Set('sync_source_id', $oDataSource->GetKey()); |
| 58 | + $oStatLog->Set('start_date', time()); |
| 59 | + $oStatLog->Set('status', 'running'); |
| 60 | + $oStatLog->AddTrace('Manual synchro'); |
| 61 | + |
| 62 | + // Get the list of SQL columns |
| 63 | + $aAttCodesExpected = array(); |
| 64 | + $aAttCodesToReconcile = array(); |
| 65 | + $aAttCodesToUpdate = array(); |
| 66 | + $sSelectAtt = 'SELECT SynchroAttribute WHERE sync_source_id = :source_id AND (update = 1 OR reconcile = 1)'; |
| 67 | + $oSetAtt = new DBObjectSet(DBObjectSearch::FromOQL($sSelectAtt), array() /* order by*/, array('source_id' => $oDataSource->GetKey()) /* aArgs */); |
| 68 | + while ($oSyncAtt = $oSetAtt->Fetch()) { |
| 69 | + if ($oSyncAtt->Get('update')) { |
| 70 | + $aAttCodesToUpdate[$oSyncAtt->Get('attcode')] = $oSyncAtt; |
45 | 71 | }
|
46 |
| - $oReplica = MetaModel::GetObject('SynchroReplica', $iId); |
47 |
| - $oReplica->DisplayDetails($oP); |
48 |
| - break; |
49 |
| - |
50 |
| - case 'oql': |
51 |
| - $sOQL = utils::ReadParam('oql', null, false, 'raw_data'); |
52 |
| - if ($sOQL == null) |
53 |
| - { |
54 |
| - throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql')); |
| 72 | + if ($oSyncAtt->Get('reconcile')) { |
| 73 | + $aAttCodesToReconcile[$oSyncAtt->Get('attcode')] = $oSyncAtt; |
55 | 74 | }
|
56 |
| - $oFilter = DBObjectSearch::FromOQL($sOQL); |
57 |
| - $oBlock1 = new DisplayBlock($oFilter, 'search', false, array('menu' => false, 'table_id' => '1')); |
58 |
| - $oBlock1->Display($oP, 0); |
59 |
| - $oP->add('<p class="page-header">'.MetaModel::GetClassIcon('SynchroReplica').Dict::S('Core:SynchroReplica:ListOfReplicas').'</p>'); |
60 |
| - $iSourceId = utils::ReadParam('datasource', null); |
61 |
| - if ($iSourceId != null) |
62 |
| - { |
63 |
| - $oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId); |
64 |
| - $oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).'</a>'); |
| 75 | + $aAttCodesExpected[$oSyncAtt->Get('attcode')] = $oSyncAtt; |
| 76 | + } |
| 77 | + |
| 78 | + // Get the list of attributes, determine reconciliation keys and update targets |
| 79 | + // |
| 80 | + if ($oDataSource->Get('reconciliation_policy') == 'use_attributes') { |
| 81 | + $aReconciliationKeys = $aAttCodesToReconcile; |
| 82 | + } elseif ($oDataSource->Get('reconciliation_policy') == 'use_primary_key') { |
| 83 | + // Override the settings made at the attribute level ! |
| 84 | + $aReconciliationKeys = array('primary_key' => null); |
| 85 | + } |
| 86 | + |
| 87 | + if (count($aAttCodesToUpdate) == 0) { |
| 88 | + $oStatLog->AddTrace('No attribute to update'); |
| 89 | + throw new SynchroExceptionNotStarted('There is no attribute to update'); |
| 90 | + } |
| 91 | + if (count($aReconciliationKeys) == 0) { |
| 92 | + $oStatLog->AddTrace('No attribute for reconciliation'); |
| 93 | + throw new SynchroExceptionNotStarted('No attribute for reconciliation'); |
| 94 | + } |
| 95 | + |
| 96 | + |
| 97 | + $aAttributesToUpdate = array(); |
| 98 | + foreach ($aAttCodesToUpdate as $sAttCode => $oSyncAtt) { |
| 99 | + $oAttDef = MetaModel::GetAttributeDef($oDataSource->GetTargetClass(), $sAttCode); |
| 100 | + if ($oAttDef->IsWritable()) { |
| 101 | + $aAttributesToUpdate[$sAttCode] = $oSyncAtt; |
65 | 102 | }
|
66 |
| - $oBlock = new DisplayBlock($oFilter, 'list', false, array('menu'=>false)); |
67 |
| - $oBlock->Display($oP, 1); |
68 |
| - break; |
| 103 | + } |
| 104 | + // Create a change used for logging all the modifications/creations happening during the synchro |
| 105 | + $oChange = MetaModel::NewObject('CMDBChange'); |
| 106 | + $oChange->Set('date', time()); |
| 107 | + $sUserString = CMDBChange::GetCurrentUserName(); |
| 108 | + $oChange->Set('userinfo', $sUserString.' '.Dict::S('Core:SyncDataExchangeComment')); |
| 109 | + $oChange->Set('origin', CMDBChangeOrigin::SYNCHRO_DATA_SOURCE); |
| 110 | + $oChange->DBInsert(); |
| 111 | + CMDBObject::SetCurrentChange($oChange); |
| 112 | + |
| 113 | + $oReplica->InitExtendedData($oDataSource); |
| 114 | + |
| 115 | + $oReplica->Synchro($oDataSource, $aReconciliationKeys, $aAttributesToUpdate, $oChange, $oStatLog); |
| 116 | + $oReplica->DBUpdate(); |
| 117 | + |
| 118 | + return $oStatLog; |
| 119 | +} |
| 120 | + |
| 121 | +try { |
| 122 | + switch ($sOperation) { |
| 123 | + case 'details': |
| 124 | + $iId = utils::ReadParam('id', null); |
| 125 | + if ($iId == null) { |
| 126 | + throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id')); |
| 127 | + } |
| 128 | + $oReplica = MetaModel::GetObject('SynchroReplica', $iId); |
| 129 | + $oReplica->DisplayDetails($oP); |
| 130 | + break; |
| 131 | + |
| 132 | + case 'oql': |
| 133 | + $sOQL = utils::ReadParam('oql', null, false, 'raw_data'); |
| 134 | + if ($sOQL == null) { |
| 135 | + throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql')); |
| 136 | + } |
| 137 | + $oFilter = DBObjectSearch::FromOQL($sOQL); |
| 138 | + $oBlock1 = new DisplayBlock($oFilter, 'search', false, array('menu' => false, 'table_id' => '1')); |
| 139 | + $oBlock1->Display($oP, 0); |
| 140 | + $oP->add('<p class="page-header">'.MetaModel::GetClassIcon('SynchroReplica').Dict::S('Core:SynchroReplica:ListOfReplicas').'</p>'); |
| 141 | + $iSourceId = utils::ReadParam('datasource', null); |
| 142 | + if ($iSourceId != null) { |
| 143 | + $oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId); |
| 144 | + $oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).'</a>'); |
| 145 | + } |
| 146 | + $oBlock = new DisplayBlock($oFilter, 'list', false, array('menu' => false)); |
| 147 | + $oBlock->Display($oP, 1); |
| 148 | + break; |
69 | 149 |
|
70 | 150 | case 'delete':
|
71 | 151 | case 'select_for_deletion':
|
72 |
| - // Redirect to the page that implements bulk delete |
73 |
| - $sDelete = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?'.$_SERVER['QUERY_STRING']; |
74 |
| - header("Location: $sDelete"); |
75 |
| - break; |
| 152 | + // Redirect to the page that implements bulk delete |
| 153 | + $sDelete = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?'.$_SERVER['QUERY_STRING']; |
| 154 | + header("Location: $sDelete"); |
| 155 | + break; |
| 156 | + |
| 157 | + case 'unlinksynchro': |
| 158 | + $iId = utils::ReadParam('id', null); |
| 159 | + if ($iId == null) { |
| 160 | + throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id')); |
| 161 | + } |
| 162 | + $oReplica = MetaModel::GetObject('SynchroReplica', $iId); |
| 163 | + $oReplica->Set('dest_id', ''); |
| 164 | + $oReplica->Set('status', 'new'); |
| 165 | + $oReplica->DBWrite(); |
| 166 | + |
| 167 | + $oStatLog = Synchro($oReplica); |
| 168 | + $oP->add(implode('<br>', $oStatLog->GetTraces())); |
| 169 | + |
| 170 | + $oReplica->DisplayDetails($oP); |
| 171 | + break; |
| 172 | + |
| 173 | + case 'unlink': |
| 174 | + $iId = utils::ReadParam('id', null); |
| 175 | + if ($iId == null) { |
| 176 | + throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id')); |
| 177 | + } |
| 178 | + $oReplica = MetaModel::GetObject('SynchroReplica', $iId); |
| 179 | + $oReplica->Set('dest_id', ''); |
| 180 | + $oReplica->Set('status', 'new'); |
| 181 | + $oReplica->DBWrite(); |
| 182 | + |
| 183 | + $oReplica->DisplayDetails($oP); |
| 184 | + break; |
| 185 | + |
| 186 | + case 'synchro': |
| 187 | + $iId = utils::ReadParam('id', null); |
| 188 | + if ($iId == null) { |
| 189 | + throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id')); |
| 190 | + } |
| 191 | + $oReplica = MetaModel::GetObject('SynchroReplica', $iId); |
| 192 | + $oStatLog = Synchro($oReplica); |
| 193 | + break; |
76 | 194 | }
|
77 | 195 | }
|
78 | 196 | catch(CoreException $e)
|
|
0 commit comments