Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
clean_old_shadow_links.php
1 <?php
40 error_reporting(E_ALL);
41 if ((php_sapi_name() != 'cli')) {
42  trigger_error("\nYou can only run this script from the command line.\n", E_USER_ERROR);
43 }
44 
45 $options = getopt('m:s:p:d:');
46 
47 if (empty($options)) {
48  print_usage();
49  exit;
50 }
51 
52 if (!isset($options['m']) || !is_dir($options['m'])) {
53  echo "\nYou need to supply the path to the System Root as the argument of -m option.
54 Run the script without argument to see its usage.\n\n";
55  exit;
56 }
57 
58 require_once $options['m'].'/core/include/init.inc';
59 
60 // If -d option is used, do not check for other options
61 if (isset($options['d'])) {
62  if (is_file($options['d'])) {
63  delete_old_shadow_links($options['d']);
64  } else {
65  echo "\nYou need to supply the path to the PHP file as the argument of -d option.
66 Run the script without argument to see its usage.\n\n";
67  }
68  exit;
69 }
70 
71 // Get old shadow links
72 $old_links = get_old_shadow_links();
73 
74 // If there are no old shadow links, print a message and quit
75 if (empty($old_links)) {
76  echo "\nThere are no old shadow links in the system.\n\n";
77  exit;
78 }
79 
80 // Print old shadow links
81 print_links($old_links);
82 
83 // If the options -s, -p and -d are not used at all, print a message to remind the user
84 if (!isset($options['s']) && !isset($options['p'])) {
85  echo '
86 You will need to run this script with -s or -p option to save the shadow links to files
87 and -d option to delete the shadow links stored in the output file generated by -p option.
88 (You have to use an SQL client like psql to execute the SQL statements generated by -s option)
89 
90 ';
91 } else {
92  // Save SQL statements to file
93  if (isset($options['s'])) {
94  save_sql_statements($old_links, $options['s']);
95  }
96 
97  // Save shadow links as array to a file
98  if (isset($options['p'])) {
99  save_linkid_array($old_links, $options['p']);
100  }
101 }
102 
103 
110 function delete_old_shadow_links($file)
111 {
112  // Require the file to get the $linkids array
113  require $file;
114 
115  // Check if $linkids array is defined
116  if (!isset($linkids) || !is_array($linkids)) {
117  echo "\nERROR: The file $file is not in a correct format.\n\n";
118  return;
119  }
120 
121  // Split the array into chunks of 100 elements
122  $chunks = array_chunk($linkids, 100);
123 
124  // Declare total deleted links variable
125  $total_deleted_links = 0;
126 
127  // Delete the old shadow links
128  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
129  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
130 
131  try {
132  foreach ($chunks as $chunk) {
133  $delete_linkids = Array();
134  foreach ($chunk as $linkid) {
135  $delete_linkids[] = MatrixDAL::quote($linkid);
136  }
137 
138  $sql = 'DELETE FROM sq_shdw_ast_lnk WHERE linkid IN ('.implode(',', $delete_linkids).')';
139  $deleted_rows = MatrixDAL::executeSql($sql);
140  $total_deleted_links += $deleted_rows;
141  }
142 
143  } catch (DALException $e) {
144  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
145  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
146  throw new Exception('Can not delete old shadow links due to the DB error: '.$e->getMessage());
147  }
148 
149  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
150  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
151 
152  echo "\n$total_deleted_links old shadow link(s) from $file were deleted successfully.\n\n";
153 
154 }//end delete_old_shadow_links()
155 
156 
164 function save_linkid_array($links, $file)
165 {
166  // Create a big PHP string with comments in it
167  $linkids = Array();
168  foreach ($links as $link) {
169  $linkids[] = "'".$link['linkid']."', /* link_type=".$link['link_type']
170  .", majorid=".$link['majorid'].", minorid=".$link['minorid']
171  ." */";
172  }
173 
174  $php = '<?php
175  $linkids = Array(
176 '.implode("\n", $linkids).'
177  );
178 ?>
179 ';
180 
181  // Save the PHP string to file
182  if (file_put_contents($file, $php) === FALSE) {
183  echo "\nERROR: Can not write PHP array to $file\n\n";
184  } else {
185  echo "\nThe PHP array to delete the old shadow links are saved to $file\n\n";
186  }
187 
188 }//end save_linkid_array()
189 
190 
198 function save_sql_statements($links, $file)
199 {
200  // Create a big SQL string with comments in it
201  $sql = '';
202  foreach ($links as $link) {
203  $sql .= 'DELETE FROM sq_shdw_ast_lnk WHERE linkid='.MatrixDAL::quote($link['linkid'])
204  .'; -- link_type='.$link['link_type'].', majorid='.$link['majorid']
205  .', minorid='.$link['minorid']."\n";
206  }
207 
208  // Save the SQL string to file
209  if (file_put_contents($file, $sql) === FALSE) {
210  echo "\nERROR: Can not write SQL statements to $file\n\n";
211  } else {
212  echo "\nThe SQL statements to delete the old shadow links are saved to $file\n\n";
213  }
214 
215 }//end save_sql_statements()
216 
217 
231 function print_links($links)
232 {
233  echo "\nList of old shadow links:\n\n";
234  // Create row format
235  $row_format = "%7s |%5s |%8s | %-55s\n";
236  $row_delimiter_format = "%'-7s-+%'-5s-+%'-8s-+%'-55s-\n";
237 
238  // Print the header
239  printf($row_format, 'linkid', 'type', 'majorid', 'minorid');
240  printf($row_delimiter_format, '', '', '', '');
241 
242  // Print the links
243  foreach ($links as $link) {
244  printf($row_format, $link['linkid'], $link['link_type'], $link['majorid'], $link['minorid']);
245  }
246 
247  echo "(Number of links: ".count($links).")\n";
248 
249 }//end print_links()
250 
251 
257 function get_old_shadow_links()
258 {
259  // Get all shadow links
260  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db');
261 
262  $sql = 'SELECT linkid, link_type, majorid, minorid FROM sq_shdw_ast_lnk ORDER BY majorid, link_type, linkid';
263  $links = MatrixDAL::executeSqlAll($sql);
264 
265  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
266 
267  // Search for old shadow links
268  $am = $GLOBALS['SQ_SYSTEM']->am;
269  $old_links = Array();
270  foreach ($links as $link) {
271  $shadow_assetid = $link['minorid'];
272  $id_parts = explode(':', $shadow_assetid);
273  if (isset($id_parts[1])) {
274  $bridge_id = $id_parts[0];
275  $bridge = $am->getAsset($bridge_id, '', FALSE);
276  if (is_null($bridge) || !method_exists($bridge, 'getAsset')) {
277  $old_links[] = $link;
278  } else {
279  //getAsset() from bridge directly so we can set the fourth param $return_null to TRUE so we don't get dummy assets.
280  $shadow_asset = $bridge->getAsset($shadow_assetid, '', FALSE, TRUE);
281  if (is_null($shadow_asset)) $old_links[] = $link;
282  }
283  }
284  }
285 
286  return $old_links;
287 
288 }//end get_old_shadow_links()
289 
290 
296 function print_usage()
297 {
298  $usage = '
299 This script is used to clean the old shadow links whose minor shadow assets are
300 no longer valid because their bridges can not find them anymore.
301 Usage:
302  php clean_old_shadow_links.php [OPTION]
303 
304 Options list:
305  -m Required. This option requires an argument which is the Matrix System Root.
306  -s Optional. This option requires a file path to save the SQL statements to.
307  -p Optional. This option requires a file path to save the PHP array to.
308  -d Optional. This option requires the path of a PHP file generated by
309  the -p option to delete old shadow links from the database.
310 
311 Example:
312  List the old shadow links:
313  php scripts/clean_old_shadow_links.php -m $PWD
314 
315  Save the SQL statements to delete old shadow links to file:
316  php scripts/clean_old_shadow_links.php -m $PWD -s delete_shd_links.sql
317 
318  Save the shadow links under PHP array format:
319  php scripts/clean_old_shadow_links.php -m $PWD -p old_shadow_links.inc
320 
321  Delete the shadow links in the PHP file:
322  php scripts/clean_old_shadow_links.php -m $PWD -d old_shadow_links.inc
323 
324 
325 ';
326  echo $usage;
327 
328 }//end print_usage()
329 
330 
331 ?>