26 error_reporting(E_ALL);
27 if (ini_get(
'memory_limit') !=
'-1') ini_set(
'memory_limit',
'-1');
28 if ((php_sapi_name() !=
'cli')) {
29 trigger_error(
"You can only run this script from the command line\n", E_USER_ERROR);
34 define(
'LOG_FILE_NAME',
'set_permissions.log');
36 if (count($argv) < 3) {
42 process_args($config);
45 require_once $config[
'system_root'].
'/core/include/init.inc';
47 define(
'LOG_FILE', SQ_SYSTEM_ROOT.
'/data/private/logs/'.LOG_FILE_NAME);
48 define(
'SYNCH_FILE', SQ_TEMP_PATH.
'/set_metadata_schema.assetid');
52 $assetids = preg_replace(
'/[\s]*/',
'', $config[
'assetids']);
55 $rootnodes = getRootNodes($assetids);
57 _disconnectFromMatrixDatabase();
58 $pid_prepare = pcntl_fork();
59 switch ($pid_prepare) {
64 _connectToMatrixDatabase();
66 $root_user = $GLOBALS[
'SQ_SYSTEM']->am->getSystemAsset(
'root_user');
74 if (!$GLOBALS[
'SQ_SYSTEM']->setCurrentUser($root_user)) {
75 echo
"Failed logging in as root user\n";
80 $schema_info = $GLOBALS[
'SQ_SYSTEM']->am->getAssetInfo($config[
'schemaid']);
82 if ($schema_info[$config[
'schemaid']][
'type_code'] !=
'metadata_schema') {
83 trigger_error(
"Asset {$config['schemaid']} is not a metadata schema\n", E_USER_ERROR);
86 trigger_error(
"Provided schemaid {$config['schemaid']} is not an asset\n", E_USER_ERROR);
89 $children = $rootnodes;
90 foreach ($rootnodes as $rootnode_id) {
91 $children += array_merge($children, array_keys(($GLOBALS[
'SQ_SYSTEM']->am->getChildren($rootnode_id))));
96 file_put_contents(SYNCH_FILE, implode(
',', $children));
99 _disconnectFromMatrixDatabase();
104 pcntl_waitpid(-1, $status);
109 pcntl_waitpid(-1, $status);
114 if (file_exists(SYNCH_FILE)) {
115 $children_str = file_get_contents(SYNCH_FILE);
117 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";
121 $children = explode(
',', $children_str);
122 $children = array_unique($children);
125 $chunk_children = array_chunk($children, $config[
'batch_size']);
126 $current_child_list = Array();
128 log_to_file(
'======================= Start Applying Metadata Schema'.date(
'd-m-Y h:i:s').
' =======================', LOG_FILE);
129 log_to_file(
"Applying schema for: " . var_export(count($children),TRUE) .
" assets \n", LOG_FILE);
132 while (!empty($chunk_children)) {
133 $current_child_list = array_pop($chunk_children);
134 $current_remaining = count($current_child_list);
139 trigger_error(
'Process failed to fork while regenerating metadata', E_USER_ERROR);
144 _connectToMatrixDatabase();
145 $GLOBALS[
'SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
150 $mm = $GLOBALS[
'SQ_SYSTEM']->getMetadataManager();
152 foreach ($current_child_list as $child_assetid) {
153 $child_asset = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($child_assetid);
154 if (!$GLOBALS[
'SQ_SYSTEM']->am->acquireLock($child_assetid,
'metadata')) {
155 log_to_file(
'Unable to acquire metadata lock for assetid ' .$child_assetid.
'. Skipping this asset.', LOG_FILE);
159 if (!$child_asset->writeAccess(
'metadata')) {
160 log_to_file(
'Do not have write access for assetid ' .$child_assetid .
'. Skipping this asset.', LOG_FILE);
161 $GLOBALS[
'SQ_SYSTEM']->am->releaseLock($child_assetid,
'metadata');
162 $GLOBALS[
'SQ_SYSTEM']->am->forgetAsset($child_asset);
166 if ($config[
'delete'] === TRUE) {
168 if (!$mm->deleteSchema($child_assetid, $config[
'schemaid'])) {
169 log_to_file(
'Failed deleting metadata schema for assetid ' . $child_assetid .
'.', LOG_FILE);
175 if (!$mm->setSchema($child_assetid, $config[
'schemaid'], $config[
'access'], $config[
'cascades'], $config[
'force'])) {
176 log_to_file(
'Failed applying metadata schema for assetid ' .$child_assetid .
'.', LOG_FILE);
180 log_to_file(
'Metadata schema '.$config[
'schemaid'].
' applied for child assetid '.$child_assetid, LOG_FILE);
183 if (!$mm->regenerateMetadata($child_assetid, NULL, $config[
'update_assets'])) {
184 log_to_file(
'Failed regenerating metadata for assetid ' .$child_assetid .
'.', LOG_FILE);
185 $GLOBALS[
'SQ_SYSTEM']->am->releaseLock($child_assetid,
'metadata');
186 $GLOBALS[
'SQ_SYSTEM']->am->forgetAsset($child_asset);
190 log_to_file(
'Regenerated Metadata for child assetid '.$child_assetid, LOG_FILE);
192 $current_remaining--;
193 echo
'-- Remaining: ' . (string) ($current_remaining + (count($chunk_children) * $config[
'batch_size'])) .
"\n";
195 $GLOBALS[
'SQ_SYSTEM']->am->releaseLock($child_assetid,
'metadata');
196 $GLOBALS[
'SQ_SYSTEM']->am->forgetAsset($child_asset);
202 $GLOBALS[
'SQ_SYSTEM']->restoreRunLevel();
204 _disconnectFromMatrixDatabase();
209 pcntl_waitpid(-1, $status);
214 if ($fork_num >= $config[
'max_threads']) {
216 pcntl_waitpid(-1, $status);
220 if (empty($chunk_children)) {
222 while ($fork_num > 0) {
224 pcntl_waitpid(-1, $status);
236 log_to_file(
'======================= Finished Applying Metadata Schema '.date(
'd-m-Y h:i:s').
' =======================', LOG_FILE);
237 if (file_exists(SYNCH_FILE)) {
252 echo
"Usage: php {$_SERVER['argv'][0]} <system_root> <assetid[,assetid]> <schema>\n";
253 echo
" php {$_SERVER['argv'][0]} <system_root> <assetid[,assetid]> <schema> [--access <granted|denied>] [-nc] [-d] [-f] [-u]\n";
254 echo
" php {$_SERVER['argv'][0]} <system_root> <assetid[,assetid]> <schema> [--max-threads <max_threads>] [--batch-size <batch_size>]\n";
256 echo
" --access granted|denied Set the schema access. Default is 'granted'.\n";
257 echo
" -nc No cascade. Don't set the cascade flag, which allows new assets to inherit the schema.\n";
258 echo
" -d Delete schema. Ignores most other options and simply removes the schema.\n";
259 echo
" -f Force application of the schema, even if the schema is already applied or granted/denied are in conflict.\n";
260 echo
" -u Notify each asset that it has been updated.\n";
261 echo
" --max-threads Maximum concurrency. Default is 3, max allowed is 5.\n";
262 echo
" --batch-size Default is 50.\n";
264 echo
"Results are logged to data/private/logs/".LOG_FILE_NAME.
"\n";
275 function process_args(&$config) {
277 $config[
'system_root'] = (isset($_SERVER[
'argv'][1])) ? $_SERVER[
'argv'][1] :
'';
278 if (empty($config[
'system_root'])) {
279 echo
"ERROR: You need to supply the path to the System Root as the first argument\n";
283 if (!is_dir($config[
'system_root']) || !is_readable($config[
'system_root'].
'/core/include/init.inc')) {
284 echo
"ERROR: Path provided doesn't point to a Matrix installation's System Root. Please provide correct path and try again.\n";
288 $config[
'assetids'] = (isset($_SERVER[
'argv'][2])) ? $_SERVER[
'argv'][2] :
'';
289 if (empty($config[
'assetids'])) {
290 echo
"ERROR: You need to specify the root nodes to apply the schema from as the second argument\n";
294 $config[
'schemaid'] = (isset($_SERVER[
'argv'][3])) ? $_SERVER[
'argv'][3] :
'';
295 if (empty($config[
'schemaid'])) {
296 echo
"ERROR: You need to specify a schema to apply as the third argument\n";
300 $config[
'access'] = get_parameterised_arg(
'--access',
'granted');
301 if ($config[
'access'] ==
'denied') {
302 $config[
'granted'] = FALSE;
304 $config[
'granted'] = TRUE;
307 $config[
'cascades'] = !get_boolean_arg(
'-nc');
308 $config[
'force'] = get_boolean_arg(
'-f');
309 $config[
'update_assets'] = get_boolean_arg(
'-u');
310 $config[
'delete'] = get_boolean_arg(
'-d');
312 $config[
'max_threads'] = (int) get_parameterised_arg(
'--max-threads', 3);
313 if ($config[
'max_threads'] > 5) {
314 $config[
'max_threads'] = 5;
315 } elseif ($config[
'max_threads'] < 1) {
316 $config[
'max_threads'] = 1;
319 $config[
'batch_size'] = (int) get_parameterised_arg(
'--batch-size', 50);
320 if ($config[
'batch_size'] < 5) {
321 $config[
'batch_size'] = 50;
325 if ($config[
'delete'] === TRUE) {
326 echo
"Will attempt to delete schema {$config['schemaid']} from asset(s) {$config['assetids']}.\n\n";
327 echo
" Update assets: {$config['update_assets']}\n";
328 echo
" Max threads: {$config['max_threads']}\n";
329 echo
" Batch size: {$config['batch_size']}\n";
331 echo
"Will attempt to set schema {$config['schemaid']} to asset(s) {$config['assetids']}.\n\n";
332 echo
" Access: {$config['access']}\n";
333 echo
" Cascade: {$config['cascades']}\n";
334 echo
" Force: {$config['force']}\n";
335 echo
" Update assets: {$config['update_assets']}\n";
336 echo
" Max threads: {$config['max_threads']}\n";
337 echo
" Batch size: {$config['batch_size']}\n";
342 if (($config[
'access'] ==
'denied') && ($config[
'force'] === TRUE)) {
343 echo
"WARNING: You are attempting to 'force' application of a schema as 'denied', which can lead to unpredictable results.\n";
344 echo
"A schema already applied with 'grant' cannot be subsequently 'denied', it must first be removed.\n";
347 echo
'Are you sure you want to continue? (y/N): ';
348 $force_denied = rtrim(fgets(STDIN, 4094));
350 if (strtoupper($force_denied) !=
'Y') {
364 function get_boolean_arg($arg) {
365 $key = array_search($arg, $_SERVER[
'argv']);
382 function get_parameterised_arg($arg, $default) {
383 $key = array_search($arg, $_SERVER[
'argv']);
385 if (($key) && (isset($_SERVER[
'argv'][$key + 1]))) {
386 return $_SERVER[
'argv'][$key + 1];
402 function get_line($prompt=
'')
406 return rtrim(fgets(STDIN, 4096));
417 function _disconnectFromMatrixDatabase()
420 if (isset($conn_id) && !empty($conn_id)) {
434 function _connectToMatrixDatabase()
436 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'db2');
445 function log_to_file($content, $file_name=
"set_metadata_schema.log")
447 file_put_contents($file_name,
'['.date(
'd-m-Y h:i:s').
'] '.$content.
"\n", FILE_APPEND);
452 function getRootNodes($action)
454 $rootnodes = explode(
',', $action);
457 $rootnodes_exists = $GLOBALS[
'SQ_SYSTEM']->am->assetExists($rootnodes);
459 $not_exists = array_diff($rootnodes, $rootnodes_exists);
460 if (!empty($not_exists)) {
461 $list_not_exists = implode(
', ', $not_exists);
462 echo
"These rootnode ids do not exists in the system: $list_not_exists \n";