Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
import_from_xml.php
1 <?php
28 define ('SQ_IN_IMPORT', 1);
29 
30 error_reporting(E_ALL);
31 if (ini_get('memory_limit') != '-1') ini_set('memory_limit', '-1');
32 
33 // enable gabage collection
34 if(function_exists ('gc_enable')) {
35  gc_enable();
36 }
37 
38 if ((php_sapi_name() != 'cli')) trigger_error("You can only run this script from the command line\n", E_USER_ERROR);
39 
40 $SYSTEM_ROOT = (isset($_SERVER['argv'][1])) ? $_SERVER['argv'][1] : '';
41 if (empty($SYSTEM_ROOT)) {
42  echo "ERROR: You need to supply the path to the System Root as the first argument\n";
43  exit();
44 }
45 
46 if (!is_dir($SYSTEM_ROOT) || !is_readable($SYSTEM_ROOT.'/core/include/init.inc')) {
47  echo "ERROR: Path provided doesn't point to a Matrix installation's System Root. Please provide correct path and try again.\n";
48  exit();
49 }
50 
51 $import_file = (isset($_SERVER['argv'][2])) ? $_SERVER['argv'][2] : '';
52 if (empty($import_file) || !is_file($import_file)) {
53  echo "You need to supply the path to the import file as the second argument\n";
54  exit();
55 }
56 
57 require_once $SYSTEM_ROOT.'/core/include/init.inc';
58 
59 if (isset($_SERVER['argv'][3]) && $_SERVER['argv'][3] == '--root-node' ) {
60  $root_node_id = (isset($_SERVER['argv'][4])) ? $_SERVER['argv'][4] : '';
61  if (empty($root_node_id)) {
62  echo "you need to supply root node under which the assets are to be imported as fourth argument\n";
63  exit();
64  }
65 }
66 
67 $root_user = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('root_user');
68 
69 require_once SQ_LIB_PATH.'/import_export/import.inc';
70 $import_actions = get_import_actions($import_file);
71 
72 //done checking authenticity of the system, first thing we check is the valid asset id for root node
73 if (isset($_SERVER['argv'][3]) && $_SERVER['argv'][3] == '--root-node' ) {
74  //we are going to try and get the asset, we dont wanna be throwing errors here, so mute them
75  error_reporting(E_NOTICE);
76  $root_node = $GLOBALS['SQ_SYSTEM']->am->getAsset($root_node_id);
77  if (is_null($root_node)) {
78  echo "\nProvided assetid is not valid for given system, Script will stop execution\n";
79  exit;
80  }
81  //restore error reporting
82  error_reporting(E_ALL);
83 
84  $import_actions['actions'][0]['action'][0]['parentid'][0] = $root_node_id;
85 
86 }
87 $total_number = count($import_actions['actions'][0]['action']);
88 
89 // overcom oracle 'end of communication' bug
90 _disconnectFromMatrixDatabase();
91 
92 // temp file to store global data, so child process can access it
93 // also used as a progress file to resume previous progress
94 $import_file_name_hash = md5($import_file);
95 define('TEMP_FILE', SQ_TEMP_PATH.'/import_from_xml_'.$import_file_name_hash.'.tmp');
96 if(is_file(TEMP_FILE)) {
97  echo "Previous progress file is detected, resuming to previous import.\n";
98  echo "Using ".TEMP_FILE."\n\n";
99  $actions_done = unserialize(file_get_contents(TEMP_FILE));
100 }
101 
102 
103 $import_action_outputs = Array();
104 $nest_content_to_fix = Array();
105 $designs_to_fix = Array();
106 // Loop through the Actions from the XML File
107 foreach ($import_actions['actions'][0]['action'] as $index => $action) {
108  // skip actions that have done before
109  // also try those previous failed actions
110  if(isset($actions_done[$action['action_id'][0]])) {
111  continue;
112  }
113 
114 
115  // remember nest content to fix
116  if($action['action_type'][0] === 'create_asset' && $action['type_code'][0] === 'Content_Type_Nest_Content') {
117  $nest_content_to_fix[] = $action['action_id'][0];
118  }
119  if($action['action_type'][0] === 'create_asset' && $action['type_code'][0] === 'Design') {
120  $designs_to_fix[] = $action['action_id'][0];
121  }
122 
123 
124 
125  // Use forked process to make sure memory usage is stable
126  $pid = pcntl_fork();
127  switch ($pid) {
128  case -1:
129  trigger_error('Process failed to fork', E_USER_ERROR);
130  exit(1);
131  break;
132  case 0:
133  // process action in forked child process
134  // connect to DB within the child process to overcome oracle stupidness
135  _connectToMatrixDatabase();
136  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_OPEN);
137  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
138  // restore the temp data from file
139  if(is_file(TEMP_FILE))
140  $import_action_outputs = unserialize(file_get_contents(TEMP_FILE));
141 
142  // check if there is hard coded assetid reference which doesn't exist in the target system
143  if(!checkAssetExists($action, 'parentid') || !checkAssetExists($action, 'assetid') || !checkAssetExists($action, 'asset')) {
144  trigger_error('Action ID "'.$action['action_id'][0].'" contains non-exist assetid reference. Action skipped.', E_USER_WARNING);
145  _disconnectFromMatrixDatabase();
146  exit(0);
147  break;
148  }
149 
150  // Execute the action
151  printActionId($action['action_id'][0]);
152  if (!execute_import_action($action, $import_action_outputs)) {
153  trigger_error('Action ID "'.$action['action_id'][0].'" could not be executed', E_USER_WARNING);
154  } else {
155  $count = $index + 1;
156  printStatus($count.'/'.$total_number);
157  }
158 
159  // blank out old value and new value returned from set attribute action.
160  // recording the attribute value content will flood our temp data file and memory
161  $new_entry = array_slice( $import_action_outputs, -1, 1, TRUE );
162  $new_entry_key = key($new_entry);
163  if(isset($new_entry[$new_entry_key]['old_value'])) unset($new_entry[$new_entry_key]['old_value']);
164  if(isset($new_entry[$new_entry_key]['new_value'])) unset($new_entry[$new_entry_key]['new_value']);
165  $import_action_outputs = array_merge($import_action_outputs, $new_entry);
166 
167  // save global temp data to file
168  $temp_string = serialize($import_action_outputs);
169  string_to_file($temp_string, TEMP_FILE);
170 
171  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
172  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
173  // Disconnect from DB
174  _disconnectFromMatrixDatabase();
175  exit(0);
176  break;
177 
178  default:
179  $status = null;
180  pcntl_waitpid(-1, $status);
181  break;
182  }//end switch
183 
184 }
185 
186 
187 // fix nest content type, regenerate the bodycopy
188 foreach ($nest_content_to_fix as $actionid) {
189  if(isset($import_action_outputs[$actionid])) {
190  $nest_content_id = $import_action_outputs[$actionid]['assetid'];
191  $nest_content = $GLOBALS['SQ_SYSTEM']->am->getAsset($nest_content_id);
192  $nest_content->_tmp['edit_fns'] = NULL;
193  $nest_content->linksUpdated();
194  }
195 }
196 
197 // we have imported a few design , lets fix them
198 foreach ($designs_to_fix as $design) {
199  if(isset($import_action_outputs[$design])) {
200  $design_id = $import_action_outputs[$design]['assetid'];
201  $vars = Array('assetid' => $design_id);
202  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
203  $hh->freestyleHipo('hipo_job_regenerate_design', $vars);
204  }
205 }
206 
207 // remove the temp file
208 if(is_file(TEMP_FILE)) unlink(TEMP_FILE);
209 
210 // disable gabage collection
211 if(function_exists ('gc_disable')) {
212  gc_disable();
213 }
214 
223 function printActionId($action_id)
224 {
225  if (strlen($action_id) > 66) {
226  $action_id = substr($action_id, 0, 66).'...';
227  }
228  printf ('%s%'.(70 - strlen($action_id)).'s', $action_id,'');
229 
230 }//end printActionId()
231 
232 
241 function printStatus($status)
242 {
243  echo "[ $status ]\n";
244 
245 }//end printStatus()
246 
247 
257 function checkAssetExists($action, $type='asset')
258 {
259  if(isset($action[$type][0]) && preg_match('/^[0-9]+$/', $action[$type][0])){
260  return ($GLOBALS['SQ_SYSTEM']->am->assetExists ($action[$type][0]));
261  }
262  return TRUE;
263 }
264 
265 
272 function _disconnectFromMatrixDatabase()
273 {
274  $conn_id = MatrixDAL::getCurrentDbId();
275  if (isset($conn_id) && !empty($conn_id)) {
277  MatrixDAL::dbClose($conn_id);
278  }//end if
279 
280 }//end _disconnectFromMatrixDatabase()
281 
282 
289 function _connectToMatrixDatabase()
290 {
291  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
292 
293 }//end _connectToMatrixDatabase()
294 
295 
296 ?>