30 error_reporting(E_ALL);
31 if (ini_get(
'memory_limit') !=
'-1') ini_set(
'memory_limit',
'-1');
32 if ((php_sapi_name() !=
'cli')) {
33 trigger_error(
"You can only run this script from the command line\n", E_USER_ERROR);
38 define(
'LOG_FILE_NAME',
'update_lookups.log');
41 process_args($config);
43 require_once $config[
'system_root'].
'/core/include/init.inc';
44 require_once SQ_INCLUDE_PATH.
'/assertions.inc';
46 define(
'LOG_FILE', SQ_SYSTEM_ROOT.
'/data/private/logs/'.LOG_FILE_NAME);
47 define(
'SYNCH_FILE', SQ_TEMP_PATH.
'/update_lookups.assetid');
49 if (empty($config[
'assetids'])) {
51 $rootnodes = $GLOBALS[
'SQ_SYSTEM']->am->getTypeAssetids(
'site', FALSE);
54 $assetids = preg_replace(
'/[\s]*/',
'', $config[
'assetids']);
57 $rootnodes = getRootNodes($assetids);
60 _disconnectFromMatrixDatabase();
65 $pid_prepare = pcntl_fork();
66 switch ($pid_prepare) {
71 _connectToMatrixDatabase();
74 $root_user = $GLOBALS[
'SQ_SYSTEM']->am->getSystemAsset(
'root_user');
75 if (!$GLOBALS[
'SQ_SYSTEM']->setCurrentUser($root_user)) {
76 trigger_error(
"Failed logging in as root user\n", E_USER_ERROR);
80 echo
"Determining assets to process...\n";
81 $children = getTreeSortedChildren($rootnodes);
84 file_put_contents(SYNCH_FILE, implode(
',', $children));
87 _disconnectFromMatrixDatabase();
92 pcntl_waitpid(-1, $status);
97 pcntl_waitpid(-1, $status);
103 if (file_exists(SYNCH_FILE)) {
104 $children_str = file_get_contents(SYNCH_FILE);
106 echo
"Unable to find Synch File, probably because the root user was not able to log in, or the user executing this script does not have permission to write to this folder.\n";
110 $children = explode(
',', $children_str);
111 $children = array_unique($children);
114 $chunk_children = array_chunk($children, $config[
'batch_size']);
115 $current_child_list = Array();
117 echo
"Updating lookups for " . count($children) .
" assets...\n";
119 log_to_file(
'======================= Start updating lookups '.date(
'd-m-Y h:i:s').
' =======================', LOG_FILE);
120 log_to_file(
"Updating lookups for " . var_export(count($children),TRUE) .
" assets \n", LOG_FILE);
122 while (!empty($chunk_children)) {
123 $current_child_list = array_pop($chunk_children);
124 $current_remaining = count($current_child_list);
129 trigger_error(
'Process failed to fork', E_USER_ERROR);
135 _connectToMatrixDatabase();
136 $GLOBALS[
'SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
140 foreach ($current_child_list as $child_assetid) {
141 $child_asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($child_assetid);
144 if (!is_object($child_asset)) {
145 log_to_file(
'Asset #'.$child_assetid.
' does not exist, skipping', LOG_FILE);
146 if ($config[
'verbose']) echo
'-- Asset #'.$child_assetid.
' does not exist, skipping' .
"\n";
149 $child_asset->updateLookups(FALSE);
150 log_to_file(
'Updated lookups for #'.$child_assetid, LOG_FILE);
152 $current_remaining--;
153 if ($config[
'verbose']) echo
'-- Remaining: ' . (string) ($current_remaining + (count($chunk_children) * $config[
'batch_size'])) .
"\n";
155 $GLOBALS[
'SQ_SYSTEM']->am->forgetAsset($child_asset);
161 $GLOBALS[
'SQ_SYSTEM']->restoreRunLevel();
163 _disconnectFromMatrixDatabase();
170 pcntl_waitpid(-1, $status);
179 log_to_file(
'======================= Finished updating lookups '.date(
'd-m-Y h:i:s').
' =======================', LOG_FILE);
180 if (file_exists(SYNCH_FILE)) {
195 echo
"Usage: php {$_SERVER['argv'][0]} <system_root> [assetid[,assetid]] [--batch-size <num>] [--verbose]\n";
197 echo
" [assetid] Assets to update lookups for (and their children). If this argument is omitted the script will run on the whole system\n";
198 echo
" --batch-size <num> Number of assets to process per fork. Default is 1000.\n";
199 echo
" --verbose Print number of assets remaining to stdout.\n";
201 echo
"Results are logged to data/private/logs/".LOG_FILE_NAME.
"\n";
212 function process_args(&$config) {
214 $config[
'system_root'] = (isset($_SERVER[
'argv'][1])) ? $_SERVER[
'argv'][1] :
'';
215 if (empty($config[
'system_root'])) {
216 echo
"ERROR: You need to supply the path to the System Root as the first argument\n";
221 if (!is_dir($config[
'system_root']) || !is_readable($config[
'system_root'].
'/core/include/init.inc')) {
222 echo
"ERROR: Path provided doesn't point to a Matrix installation's System Root. Please provide correct path and try again.\n";
227 $config[
'assetids'] = (isset($_SERVER[
'argv'][2])) ? trim($_SERVER[
'argv'][2]) :
'';
228 if (empty($config[
'assetids']) || strpos($config[
'assetids'],
'--') === 0) {
229 echo
"\nWARNING: You are running this update lookup on the whole system.\nThis is fine but it may take a long time\n\nYOU HAVE 5 SECONDS TO CANCEL THIS SCRIPT... ";
230 for ($i = 1; $i <= 5; $i++) {
234 $config[
'assetids'] =
'';
237 $config[
'batch_size'] = (int) get_parameterised_arg(
'--batch-size', 1000);
238 $config[
'verbose'] = (int) get_boolean_arg(
'--verbose');
241 echo
"Updating lookups from asset(s): {$config['assetids']}.\n";
242 echo
"Batch size: {$config['batch_size']}\n";
254 function get_boolean_arg($arg) {
255 $key = array_search($arg, $_SERVER[
'argv']);
272 function get_parameterised_arg($arg, $default) {
273 $key = array_search($arg, $_SERVER[
'argv']);
275 if (($key) && (isset($_SERVER[
'argv'][$key + 1]))) {
276 return $_SERVER[
'argv'][$key + 1];
292 function get_line($prompt=
'')
296 return rtrim(fgets(STDIN, 4096));
307 function _disconnectFromMatrixDatabase()
310 if (isset($conn_id) && !empty($conn_id)) {
324 function _connectToMatrixDatabase()
326 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'db2');
335 function log_to_file($content, $file_name=
"set_metadata_schema.log")
337 file_put_contents($file_name,
'['.date(
'd-m-Y h:i:s').
'] '.$content.
"\n", FILE_APPEND);
342 function getRootNodes($action)
344 $rootnodes = explode(
',', $action);
347 $rootnodes_exists = $GLOBALS[
'SQ_SYSTEM']->am->assetExists($rootnodes);
349 $not_exists = array_diff($rootnodes, $rootnodes_exists);
350 if (!empty($not_exists)) {
351 $list_not_exists = implode(
', ', $not_exists);
352 echo
"These rootnode ids do not exists in the system: $list_not_exists \n";
366 function getTreeSortedChildren($assetids)
370 $todo_normal = Array();
371 $todo_shadows = Array();
373 foreach ($assetids as $assetid) {
375 $id_parts = explode(
':', $assetid);
376 if (isset($id_parts[1])) {
377 $todo_shadows = array_merge($todo_shadows, array_keys($GLOBALS[
'SQ_SYSTEM']->am->getChildren($assetid)));
379 $asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($assetid);
380 if ($asset instanceof
Bridge) {
381 if (!method_exists($asset,
'getChildren')) {
382 trigger_localised_error(
'SYS0204', E_USER_WARNING, $asset->name);
384 $todo_shadows = array_merge($todo_shadows, array_keys($asset->getChildren($assetid)));
388 $where =
'l.minorid = :assetid';
389 $where = $GLOBALS[
'SQ_SYSTEM']->constructRollbackWhereClause($where,
't');
390 $where = $GLOBALS[
'SQ_SYSTEM']->constructRollbackWhereClause($where,
'l');
391 $sql =
'SELECT t.treeid
392 FROM '.SQ_TABLE_RUNNING_PREFIX.
'ast_lnk_tree t INNER JOIN '.SQ_TABLE_RUNNING_PREFIX.
'ast_lnk l ON t.linkid = l.linkid
400 }
catch (Exception $e) {
401 throw new Exception(
'Unable to get treeid for minorid: '.$assetid.
' due to database error: '.$e->getMessage());
404 $sql =
'SELECT l.minorid, MAX(LENGTH(t.treeid)) as length
405 FROM '.SQ_TABLE_RUNNING_PREFIX.
'ast_lnk_tree t
406 INNER JOIN '.SQ_TABLE_RUNNING_PREFIX.
'ast_lnk l ON t.linkid = l.linkid
408 $where =
't.treeid LIKE :treeid
409 GROUP BY l.minorid ORDER BY length';
411 $where = $GLOBALS[
'SQ_SYSTEM']->constructRollbackWhereClause($where,
't');
412 $where = $GLOBALS[
'SQ_SYSTEM']->constructRollbackWhereClause($where,
'l');
418 }
catch (Exception $e) {
419 throw new Exception(
'Unable to get minorids for treeid: '.$treeid[0][
'treeid'].
' due to database error: '.$e->getMessage());
422 $todo_normal = array_merge($todo_normal, $new_assets);
428 usort($todo_normal, create_function(
'$a, $b',
'return $a[\'length\'] > $b[\'length\'];'));
429 $todo_assetids = Array();
430 foreach($todo_normal as $asset_info) {
431 $todo_assetids[] = $asset_info[
'minorid'];
434 $todo_assetids = array_unique(array_merge($todo_assetids, $todo_shadows));
436 return $todo_assetids;