Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
hipo_job_create_links.inc
1 <?php
17 require_once SQ_SYSTEM_ROOT.'/core/hipo/hipo_job.inc';
18 
44 {
45 
46 
52  function HIPO_Job_Create_Links($code_name='')
53  {
54  $this->HIPO_Job($code_name);
55 
56  }//end constructor
57 
58 
65  function getCodeName()
66  {
67  return parent::getCodeName().'-'.md5(implode('-',array_keys($this->_running_vars['assets'])));
68 
69  }//end getCodeName()
70 
71 
78  function getHipoName()
79  {
80  return translate('hipo_name_create_links');
81 
82  }//end getHipoName()
83 
84 
92  function getInitialStepData()
93  {
94  return Array(
95  Array(
96  'name' => translate('hipo_confirmation'),
97  'function_call' => Array(
98  'paint_function' => 'paintConfirmation',
99  'process_function' => 'processConfirmation',
100  ),
101  'running_mode' => 'web',
102  'auto_step' => FALSE,
103  'skip_step' => FALSE,
104  'allow_cancel' => TRUE,
105  'percent_done' => 0,
106  'complete' => FALSE,
107  'message' => '',
108  ),
109  Array(
110  'name' => translate('hipo_creating_links'),
111  'function_call' => Array(
112  'process_function' => 'processCreateLinks',
113  ),
114  'running_mode' => 'server',
115  'auto_step' => TRUE,
116  'skip_step' => FALSE,
117  'allow_cancel' => TRUE,
118  'percent_done' => 0,
119  'complete' => FALSE,
120  'message' => '',
121  ),
122  Array(
123  'name' => translate('hipo_updating_lookups'),
124  'hipo_job' => Array(
125  'init_details_function' => 'updateLookups',
126  ),
127  'running_mode' => 'server',
128  'auto_step' => TRUE,
129  'skip_step' => FALSE,
130  'allow_cancel' => TRUE,
131  'percent_done' => 0,
132  'complete' => FALSE,
133  'message' => '',
134  ),
135  Array(
136  'name' => translate('hipo_cascading_options'),
137  'function_call' => Array(
138  'paint_function' => 'paintInterface',
139  'process_function' => 'processInterface',
140  ),
141  'running_mode' => 'web',
142  'auto_step' => FALSE,
143  'skip_step' => FALSE,
144  'allow_cancel' => FALSE,
145  'percent_done' => 0,
146  'complete' => FALSE,
147  'message' => '',
148  ),
149  Array(
150  'name' => translate('hipo_cascading_permissions'),
151  'hipo_job' => Array(
152  'init_details_function' => 'cascadePermissions',
153  ),
154  'running_mode' => 'server',
155  'auto_step' => TRUE,
156  'skip_step' => FALSE,
157  'allow_cancel' => FALSE,
158  'percent_done' => 0,
159  'complete' => FALSE,
160  'message' => '',
161  ),
162  Array(
163  'name' => translate('hipo_cascading_metadata'),
164  'hipo_job' => Array(
165  'init_details_function' => 'cascadeMetadata',
166  ),
167  'running_mode' => 'server',
168  'auto_step' => TRUE,
169  'skip_step' => FALSE,
170  'allow_cancel' => FALSE,
171  'percent_done' => 0,
172  'complete' => FALSE,
173  'message' => '',
174  ),
175  Array(
176  'name' => translate('hipo_cascading_workflow'),
177  'hipo_job' => Array(
178  'init_details_function' => 'cascadeWorkflow',
179  ),
180  'running_mode' => 'server',
181  'auto_step' => TRUE,
182  'skip_step' => FALSE,
183  'allow_cancel' => FALSE,
184  'percent_done' => 0,
185  'complete' => FALSE,
186  'message' => '',
187  ),
188  Array(
189  'name' => translate('hipo_cascading_content_tags'),
190  'hipo_job' => Array(
191  'init_details_function' => 'cascadeTags',
192  ),
193  'running_mode' => 'server',
194  'auto_step' => TRUE,
195  'skip_step' => FALSE,
196  'allow_cancel' => FALSE,
197  'percent_done' => 0,
198  'complete' => FALSE,
199  'message' => '',
200  ),
201  Array(
202  'name' => translate('hipo_cascading_roles'),
203  'hipo_job' => Array(
204  'init_details_function' => 'cascadeRoles',
205  ),
206  'running_mode' => 'server',
207  'auto_step' => TRUE,
208  'skip_step' => FALSE,
209  'allow_cancel' => FALSE,
210  'percent_done' => 0,
211  'complete' => FALSE,
212  'message' => '',
213  ),
214  Array(
215  'name' => translate('hipo_refreshing_asset_map'),
216  'function_call' => Array(
217  'paint_function' => 'paintRefresh',
218  'process_function' => 'processRefresh',
219  ),
220  'running_mode' => 'web',
221  'auto_step' => TRUE,
222  'skip_step' => FALSE,
223  'allow_cancel' => FALSE,
224  'percent_done' => 0,
225  'complete' => FALSE,
226  'message' => '',
227  ),
228  );
229 
230  }//end getInitialStepData()
231 
232 
240  function prepare()
241  {
242  if (empty($this->_running_vars['assets'])) {
243  trigger_localised_error('HIPO0026', E_USER_WARNING);
244  return '';
245  }
246  if (!isset($this->_running_vars['to_parent_assetid'])) {
247  trigger_localised_error('HIPO0025', E_USER_WARNING);
248  return '';
249  }
250  if (!isset($this->_running_vars['to_parent_pos'])) {
251  trigger_localised_error('HIPO0024', E_USER_WARNING);
252  return '';
253  }
254 
255  $this->_running_vars['assets_children'] = Array();
256 
257  // an array of assetids that are not supposed to be trashed when Safe-Trash = Yes
258  $this->_running_vars['do_not_trash'] = Array();
259 
260  // for the sake of backwards compatibility, allow for a single link to be specified for an asset instead of an array of links
261  // transform any asset link info given in the old format
262  for (reset($this->_running_vars['assets']); NULL !== ($assetid = key($this->_running_vars['assets'])); next($this->_running_vars['assets'])) {
263  $links = current($this->_running_vars['assets']);
264  if (isset($links['linkid']) || isset($links['link_type']) || isset($links['parentid'])) {
265  $this->_running_vars['assets'][$assetid] = Array($links);
266  }
267  }
268 
269  return parent::prepare();
270 
271  }//end prepare()
272 
273 
284  function initialise($source_code_name=NULL)
285  {
286  // get a list of links that will be affected by this change
287  if ($this->_running_vars['link_action'] == 'move') {
288  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['to_parent_assetid']);
289  $assets = $this->_running_vars['assets'];
290  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
291  // Check if the assets have been moved to the trash. If there are any, warn about which links will be affected
292  if ($new_parent->id == $trash_folder->id) {
293  // if we are moving to the trash folder, we need to check if the Safe-Trash pref has been enabled
294  $safe_trash = $GLOBALS['SQ_SYSTEM']->getUserPrefs('user', 'SQ_USER_SAFE_TYPE3_TRASH');
295 
296  // when checking for the number of links left in the system, make sure we disregard
297  // any link to the trash folder because even if this asset is already in the trash,
298  // we should warn about deleting it
299  for (reset($assets); NULL !== ($assetid = key($assets)); next($assets)) {
300  $links = current($assets);
301 
302  for (reset($links); NULL !== ($link_idx = key($links)); next($links)) {
303  $current = current($links);
304 
305  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
306  $trash_link = $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($trash_folder->id, $asset->id, SQ_LINK_TYPE_1 | SQ_LINK_TYPE_2);
307  $num_other_links = $GLOBALS['SQ_SYSTEM']->am->countLinks($asset->id, 'minor', SQ_LINK_TYPE_1 | SQ_LINK_TYPE_2, '', TRUE, $current['linkid']);
308 
309  if (!empty($trash_link)) $num_other_links--;
310  if (!$num_other_links) {
311  // now lets get all the other links this asset has in the system and
312  // display them to the user
313  // note that we are also going to ask the major asset in the link
314  // to describe it so it makes sense to the user looking at it
315  $affected_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($asset->id, SQ_LINK_TYPE_3 | SQ_LINK_NOTICE, '', TRUE, 'minor');
316  $safe_trash_cron_job = $GLOBALS['SQ_SYSTEM']->am->getLinks($asset->id, SQ_LINK_TYPE_3 | SQ_LINK_NOTICE, 'cron_job_attempt_safe_trash', TRUE, 'minor');
317 
318  // We can't trust $affected_links to contain all TYPE_3|NOTICE
319  // links, as getLinks() also returns ALL shadow links. So weed
320  // out any links that aren't TYPE_3|NOTICE
321  foreach ($affected_links as $linkid => $affected_link) {
322  if (!($affected_link['link_type'] & (SQ_LINK_TYPE_3 | SQ_LINK_NOTICE))) {
323  unset($affected_links[$linkid]);
324  }
325  }
326 
327  // We can't use array_diff() because it does a string comparison
328  // ("Array" == "Array".... ooh nasty). So we will trawl through the
329  // array to find the cron job and pluck it out
330  if (!empty($safe_trash_cron_job)) {
331  foreach (array_keys($affected_links) as $affected_link_key) {
332  if ($affected_links[$affected_link_key]['linkid'] == $safe_trash_cron_job[0]['linkid']) {
333  unset($affected_links[$affected_link_key]);
334  break;
335  }
336  }
337  }
338 
339  if (!empty($affected_links)) {
340  $this->_running_vars['affected_links'][$assetid] = $affected_links;
341  }
342 
343  }//end if !$num_other_links
344 
345  // if we can't Safe-Trash for any reason whatsoever, then
346  // let them know
347  if ($safe_trash) {
348  $trash_errors = $GLOBALS['SQ_SYSTEM']->am->canSafeTrashAsset($assetid, $current['linkid'], FALSE);
349  if ($trash_errors) {
350  $this->_running_vars['do_not_trash'][$assetid] = $trash_errors;
351  $this->_running_vars['do_not_trash'][$assetid]['name'] = $asset->name;
352  }
353  }
354  }//end for ($links)
355  }//end for ($assets)
356 
357  }//end if the assets have been moved to the trash
358  }//end if action = move
359 
360  $this->_running_vars['can_skip_cascade'] = TRUE;
361 
362  return parent::initialise($source_code_name);
363 
364  }//end initialise()
365 
366 
380  function paintConfirmation(&$step_data, &$o, $prefix)
381  {
382  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['to_parent_assetid']);
383  $assets = $this->_running_vars['assets'];
384  if (isset($this->_running_vars['reordered_assets'])) {
385  $reordered_assets = $this->_running_vars['reordered_assets'];
386  }
387 
388  if ($this->_running_vars['link_action'] == 'create') {
389 
390  // We are creating a new link
391  $o->openSection(translate('new_link_confirmation'));
392  if (!empty($this->_tmp['message'])) {
393  $o->openField('<span style="color: #FF0000;">Error</span>');
394  echo $this->_tmp['message'];
395  $o->closeField();
396  }
397 
398  $o->openField('');
399  echo '<p>'.translate('hipo_confirm_new_links', htmlentities($new_parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)).'</p>';
400  echo '<ul>';
401  for (reset($assets); NULL !== ($assetid = key($assets)); next($assets)) {
402  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
403  $current = current($assets);
404  foreach ($current as $link) {
405  $parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['parentid']);
406  echo '<li>"'.translate('hipo_from_under', htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), htmlentities($parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)).'</li>';
407  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($parent);
408  }
409  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
410  }
411  echo '</ul>';
412  echo '<p>'.translate('hipo_confirm_abort').'</p>';
413  $o->closeField();
414  $o->closeSection();
415 
416  } else if ($this->_running_vars['link_action'] == 'move') {
417 
418  // we are moving an asset
419  $o->openSection(translate('hipo_move_confirmation'));
420 
421  if (!empty($this->_tmp['message'])) {
422  $o->openField('<span style="color: #FF0000;">'.translate('error').'</span>');
423  echo $this->_tmp['message'];
424  $o->closeField();
425  }
426 
427  // Check if any assets were re-ordered outside the HIPO job (ie, parentid == to_parent_id)
428  // and print them here to avoid confusion
429  if (!empty($reordered_assets)) {
430  $o->openField('&nbsp;');
431  echo '<p>'.translate('hipo_assets_not_require_move', htmlentities($new_parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)).'</p>';
432  echo '<ul>';
433  for (reset($reordered_assets); NULL !== ($assetid = key($reordered_assets)); next($reordered_assets)) {
434  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
435  echo '<li>"'.htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET).'".</li>';
436  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
437  }
438  echo '</ul>';
439  $o->closeField();
440  }
441 
442  if ($new_parent->id == $GLOBALS['SQ_SYSTEM']->am->getSystemAssetid('trash_folder')) {
443 
444  // We are moving to trash - lots of special stuff to do
445  $this->_paintMoveToTrashConfirmation($o, $prefix);
446 
447  } else {
448 
449  // We are moving somewhere else
450  $o->openField('');
451  echo '<p>'.translate('hipo_confirm_move_under', htmlentities($new_parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)).'</p>';
452  echo '<ul>';
453  for (reset($assets); NULL !== ($assetid = key($assets)); next($assets)) {
454  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
455  $current = current($assets);
456  foreach ($current as $link) {
457  $parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['parentid']);
458  echo '<li>'.translate('hipo_from_under', htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), htmlentities($parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)).'</li>';
459  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($parent);
460  }
461  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
462  }
463  echo '</ul>';
464  $o->closeField();
465 
466  }//end else
467 
468  $o->closeSection();
469 
470  }//end if action is 'move'
471 
472  $o->addHiddenField('form_submitted', 1);
473  return TRUE;
474 
475  }//end paintConfirmation()
476 
477 
487  function _paintMoveToTrashConfirmation(&$o, $prefix)
488  {
489  if (!empty($this->_running_vars['remap_choices'])) {
490 
491  // They've chosen an asset to remap to but need to choose which of its URLs to use
492  $this->_paintRemapURLChooser($o, $prefix);
493 
494  } else {
495 
496  // check if the Safe-Trash pref has been enabled
497  $safe_trash = $GLOBALS['SQ_SYSTEM']->getUserPrefs('user', 'SQ_USER_SAFE_TYPE3_TRASH');
498  $assets = $this->_running_vars['assets'];
499 
500  // work out how many assets do we really have to trash
501  // If we have nothing to trash, we no longer take out the "next"
502  // button because of the possibility for marking for Safe-Trash
503  $nothing_to_trash = FALSE;
504  $not_to_trash = 0;
505  if ($safe_trash) {
506  $to_trash = count($assets);
507  $not_to_trash = count($this->_running_vars['do_not_trash']);
508  $nothing_to_trash = ($not_to_trash == $to_trash);
509  }
510 
511  $o->openField('');
512 
513  // Ask them to confirm that they want to trash all these assets
514  if (count($assets) - $not_to_trash > 0) {
515  echo translate('hipo_confirm_move_trash', count($assets) - $not_to_trash).'</p>';
516  if (isset($this->_hipo_vars['no_next']) && $this->_hipo_vars['no_next']) {
517  // if no next button printed, modify the confirm message a little
518  echo '<p>'.translate('hipo_abort').'</p>';
519  } else {
520  echo '<p>'.translate('hipo_confirm_abort').'</p>';
521  }
522  }
523 
524  // Print Safe-Trash notices
525  if ($safe_trash && $not_to_trash > 0) {
526  if (count($assets)== $not_to_trash) {
527  ?><p><strong class="sq-backend-warning"><?php echo translate('hipo_warning_safe_trash_all');?></strong></p><?php
528  } else {
529  ?><p><strong class="sq-backend-warning"><?php echo translate('hipo_warning_safe_trash_few', count($assets), $not_to_trash);?></strong></p><?php
530  }
531  }
532 
533  // Warn that shadow assets will not be trashed
534  $shadow_assets = Array();
535  foreach ($assets as $one_id => $one_info) {
536  if (strpos($one_id,':')) $shadow_assets[] = $one_id;
537  }
538  if (!empty($shadow_assets)) {
539  $shadow_info_array = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo($shadow_assets);
540  echo '<p><strong class="sq-backend-warning">'.translate('hipo_immediate_delete_shadow').':</strong>';
541  echo '<ul>';
542  foreach ($shadow_info_array as $shadow_info) {
543  echo '<li>'.$shadow_info['short_name'].'</li>';
544  }
545  echo '</ul></p>';
546  }
547 
548  $o->closeField();
549 
550  // Paint the list of affected assets, with appropriate warning message depending on
551  // whether we are Safe-Trashing ('those assets will be affected' / 'you can't delete these assets'
552  if ($safe_trash) {
553  $affected_title = translate('hipo_safe_trash_linking_title');
554  $warning_msg = translate('hipo_safe_trash_linking_msg');
555  } else {
556  $affected_title = translate('hipo_trash_warning_affected_title');
557  $warning_msg = translate('hipo_trash_warning_affected_msg');
558  }
559  $this->_paintAffectedAssetsWarning($o, $affected_title, $warning_msg);
560 
561  if ($safe_trash && !empty($this->_running_vars['do_not_trash'])) {
562  // Paint other safe-trash sections
563  $this->_paintSafeTrashStatusWarning($o);
565  $this->_paintMarkForDeletionList($o, $prefix);
566  }
567 
568  if (!$nothing_to_trash) {
569  $this->_paintRemapAssetChooser($o, $prefix);
570  }
571  }//end else remap assetid not submitted
572 
573  }//end _paintMoveToTrashConfirmation()
574 
575 
589  function _paintAffectedAssetsWarning(&$o, $title, $warning_msg)
590  {
591  // when checking for the number of links left in the system, make sure we disregard
592  // any link to the trash folder because even if this asset is already in the trash,
593  // we should warn about deleting it
594  $affected_links = array_get_index($this->_running_vars, 'affected_links', Array());
595  if (!empty($affected_links)) {
596  $o->addJsInclude(sq_web_path('lib').'/js/tooltip.js');
597  $o->openField($title, 'new_line');
598  echo '<p>'.$warning_msg.'</p>';
599  foreach ($affected_links as $assetid => $links) {
600  echo '<br />'.translate('hipo_trash_warning_asset_linked_to', get_asset_tag_line($assetid), '<u class="clickable" onclick="toggleNextElt(this, \'TABLE\')" title="'.translate('click_to_toggle_details').'">'.translate('n_assets', count($links)).'</u>');
601  ?>
602  <table class="sq-backend-table" style="width: 80%; margin-left: 20px; display: none;">
603  <?php
604  foreach ($links as $link_data) {
605  $major = $GLOBALS['SQ_SYSTEM']->am->getAsset($link_data['majorid'], $link_data['major_type_code']);
606  $link_description = $major->describeLink($link_data['linkid']);
607  ?>
608  <tr>
609  <td><?php echo get_asset_tag_line($major->id); ?></td>
610  <td><?php echo (!empty($link_description)) ? $link_description : ''; ?></td>
611  </tr>
612  <?php
613  }//end foreach
614  ?>
615  </table>
616  <?php
617  }//end foreach
618  echo '<br /><br />';
619  $o->closeField();
620  }//end if any affected links
621 
622  }//end _paintAffectedAssetsWarning()
623 
624 
634  {
635  // paint the not safe status
636  $warning_painted = FALSE;
637  foreach ($this->_running_vars['do_not_trash'] as $id => $data) {
638  if (isset($data['status'])) {
639  if (!$warning_painted) {
640  $o->openField(translate('hipo_safe_trash_status_title'), 'new_line');
641  ?><p><?php echo translate('hipo_safe_trash_status_msg') ?></p><?php
642  echo '<ul>';
643  $warning_painted = TRUE;
644  }
645  echo '<li>';
646  echo translate('asset_format', $data['name'], $id).' - ';
647  echo translate('current_status').': ';
648  echo get_asset_status_icon($data['status']).get_status_description($data['status']).'<br />';
649  echo '</li>';
650  }
651  }
652  if ($warning_painted) {
653  echo '</ul>';
654  $o->closeField();
655  }
656 
657  }//end _paintSafeTrashStatusWarning()
658 
659 
669  {
670  $warning_painted = FALSE;
671  foreach ($this->_running_vars['do_not_trash'] as $id => $data) {
672  if (isset($data['children'])) {
673  if (!$warning_painted) {
674  $o->openField(translate('hipo_safe_trash_children_title'), 'new_line');
675  echo '<p>'.translate('hipo_safe_trash_children_msg').'</p>';
676  echo '<ul>';
677  $warning_painted = TRUE;
678  }
679 
680  $details = '<ul style="display: none">';
681  $problem_child_count = 0;
682  foreach ($data['children'] as $child_info) {
683  $details .= '<li>'.translate('asset_format', $child_info['name'], $child_info['minorid']);
684  if ($child_info['link_type'] == SQ_LINK_TYPE_3 || $child_info['link_type'] == SQ_LINK_NOTICE) {
685  $details .= ' - '.translate('hipo_warning_safe_trash_link');
686  $problem_child_count++;
687  } else if ($child_info['status'] >= SQ_STATUS_LIVE) {
688  $details .= ' - '.translate('current_status').': '.get_asset_status_icon($child_info['status']).get_status_description($child_info['status']);
689  $problem_child_count++;
690  }
691  $details .= '</li>';
692  }
693  $details .= '</ul>';
694 
695  $code = ($problem_child_count == 1) ? 'hipo_safe_trash_child_label_one' : 'hipo_safe_trash_child_label_many';
696  $sub_code = ($problem_child_count == 1) ? '1_child' : 'n_children';
697  echo '<li>'.translate($code, translate('asset_format', $data['name'], $id), '<u class="clickable" onclick="toggleNextElt(this, \'UL\')" title="'.translate('click_to_toggle_details').'">'.translate($sub_code, $problem_child_count).'</u>');
698  echo $details;
699  echo '</li>';
700  }
701  }
702  if ($warning_painted) {
703  echo '</ul>';
704  $o->closeField();
705  }
706 
707  }//end _paintSafeTrashChildrenWarning()
708 
709 
719  function _paintMarkForDeletionList(&$o, $prefix)
720  {
721  $o->openField(translate('hipo_safe_trash_mark_future_title'), 'new_line');
722 
723  $assetids = array_keys($this->_running_vars['do_not_trash']);
724  $asset_info = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo($assetids);
725 
726  ?><p>The assets that cannot be trashed due to Safe-Trash rules are listed below. Selecting assets from this list will mark them for future trashing. This creates a cron job that will automatically trash the asset as soon as the Safe-Trash rules are satisfied.</p>
727 
728  <div id="<?php echo $prefix ?>_mark">
729  <?php
730  if (count($assetids) > 1) {
731  // enable select-all
732  ?>
733  <input type="checkbox" id="<?php echo $prefix ?>_mark_all" onclick="inputs = this.parentNode.getElementsByTagName('INPUT'); for (i = 0; i &lt; inputs.length; i++) { if ((inputs[i].type == 'checkbox') && (inputs[i]!= this)) inputs[i].checked = this.checked; }">
734  <label for="<?php echo $prefix ?>_mark_all"><em><?php echo translate('select_all'); ?></em></label>
735  <hr />
736  <?php
737  $onclick = 'onclick="selall = document.getElementById(\''.$prefix.'_mark_all\'); inputs = this.parentNode.parentNode.getElementsByTagName(\'INPUT\'); sel_value = true; for (i = 0; i &lt; inputs.length; i++) { if ((inputs[i].type == \'checkbox\') && (inputs[i] != selall)) { sel_value = sel_value && inputs[i].checked; } if (!sel_value) break; } selall.checked = sel_value;"';
738  } else {
739  $onclick = '';
740  }
741  foreach ($assetids as $assetid) {
742  ?>
743  <div>
744  <input type="checkbox" name="<?php echo $prefix ?>_mark[<?php echo $assetid ?>]" id="<?php echo $prefix ?>_mark_<?php echo $assetid ?>" value="1" <?php echo $onclick; ?> >
745  <label for="<?php echo $prefix ?>_mark_<?php echo $assetid ?>">
746  <?php
747  echo get_asset_type_icon($asset_info[$assetid]['type_code']);
748  echo translate('asset_format', $asset_info[$assetid]['name'], $assetid);
749  ?>
750  </label>
751  </div>
752  <?php
753  }
754  ?>
755  </div>
756  <?php
757  echo '<br />';
758  $o->closeField();
759 
760  }//end _paintMarkForDeletionList()
761 
762 
772  function _paintRemapAssetChooser(&$o, $prefix)
773  {
774  // Paint the remap-URLs section if appropriate
775  $existing_urls = $GLOBALS['SQ_SYSTEM']->am->getAssetURL(array_keys($this->_running_vars['assets']));
776  foreach ($existing_urls as $url) {
777  if (!empty($url)) {
778  // At least one real URL exists, so ask if they want to remap URLs
779  $o->openField(translate('hipo_trash_url_remapping_title'), 'new_line');
780  echo '<p>'.translate('hipo_trash_url_remapping_msg').'</p>';
781  asset_finder($prefix.'_remap_new_url', NULL, Array(), 'sq_sidenav', isset($_GET['SQ_BACKEND_PAGE'])? FALSE : TRUE);
782  $o->closeField();
783  break;
784  }
785  }
786 
787  }//end _paintRemapAssetChooser()
788 
789 
799  function _paintRemapURLChooser(&$o, $prefix)
800  {
801  $o->openField('');
802  echo '<p>'.translate('hipo_trash_url_remapping_choose_url').':</p>';
803  foreach ($this->_running_vars['remap_choices'] as $i => $url) {
804  radio_button($prefix.'_chosen_remap_url', $i, ($i==0));
805  label($url['url'], $prefix.'_chosen_remap_url_'.$i);
806  echo '<br />';
807  }
808  $o->closeField();
809 
810  }//end _paintRemapURLChooser()
811 
812 
823  function processConfirmation(&$step_data, $prefix)
824  {
825  // if we are moving to the trash and they want to remap the URLs of the asset that
826  // is being trashed to another asset, go through and do all this for them
827  if (isset($_POST['form_submitted'])) {
828  if (isset($_POST[$prefix.'_chosen_remap_url'])) {
829  $dest_url_data = $this->_running_vars['remap_choices'][(int)$_POST[$prefix.'_chosen_remap_url']];
830  $remap_url = ($dest_url_data['http'] ? 'http' : 'https').'://'.$dest_url_data['url'];
831  $rm = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('remap_manager');
832  foreach ($this->_running_vars['assets'] as $source_assetid => $links) {
833  if (isset($this->_running_vars['do_not_trash'][$source_assetid])) {
834  continue;
835  }
836  if (!$rm->remapAllURLs($source_assetid, $remap_url)) {
837  $source_asset =$GLOBALS['SQ_SYSTEM']->am->getAsset($source_assetid);
838  $this->_tmp['message'] = '<span style="color: #FF0000;">'.translate('hipo_cannot_remap_urls', htmlentities($source_asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), $remap_url).'</span>';
839  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($remap_asset);
840  return TRUE;
841  }
842  }
843  }
844 
845  if (!empty($_POST[$prefix.'_remap_new_url']['assetid'])) {
846  $dest_assetid = $_POST[$prefix.'_remap_new_url']['assetid'];
847  $dest_urls = $GLOBALS['SQ_SYSTEM']->am->getURLs($dest_assetid);
848  switch (count($dest_urls)) {
849  case 1:
850  // Target asset has exactly one URL - do the remap straight away
851  $dest_url_data = reset($dest_urls);
852  $rm = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('remap_manager');
853  foreach ($this->_running_vars['assets'] as $source_assetid => $links) {
854  if (isset($this->_running_vars['do_not_trash'][$source_assetid])) {
855  continue;
856  }
857  if (!$rm->remapAllURLs($source_assetid, ($dest_url_data['http'] ? 'http' : 'https').'://'.$dest_url_data['url'])) {
858  $source_asset =$GLOBALS['SQ_SYSTEM']->am->getAsset($source_assetid);
859  $this->_tmp['message'] = '<span style="color: #FF0000;">'.translate('hipo_cannot_remap_urls', htmlentities($source_asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), $dest_url_data['url']).'</span>';
860  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($remap_asset);
861  return TRUE;
862  }
863  }
864  break;
865  case 0:
866  // Cannot remap, the target asset has no URLs
867  $remap_asset =$GLOBALS['SQ_SYSTEM']->am->getAsset($dest_assetid);
868  $this->_tmp['message'] = '<span style="color: #FF0000;">'.translate('hipo_cannot_remap_links_without_destination_url', htmlentities($remap_asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)).'</span>';
869  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($remap_asset);
870  return TRUE;
871  break;
872  default:
873  // Target asset has several URLs; ask the user which one to use
874  $this->_running_vars['remap_choices'] = $dest_urls;
875  $step_data['percent_done'] = 75;
876  $ste_data['complete'] = FALSE;
877  return TRUE;
878  break;
879  }//end switch
880  }//end if remap assetid supplied
881 
882  if (isset($_POST[$prefix.'_mark'])) {
883  $this->_running_vars['mark_for_deletion'] = $_POST[$prefix.'_mark'];
884  }
885 
886  }//end if HIPO form submitted
887 
888 
889  if ($step_data['percent_done'] == 0) {
890  $step_data['percent_done'] = 50;
891  } else {
892  $step_data['percent_done'] = 100;
893  $step_data['complete'] = TRUE;
894  }
895 
896  return TRUE;
897 
898  }//end processConfirmation()
899 
900 
910  function processCreateLinks(&$step_data, $prefix)
911  {
912  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
913  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
914 
915  if (!isset($this->_running_vars['process_create_links'])) {
916  $this->_running_vars['process_create_links'] = $this->_running_vars['assets'];
917  }
918  if (!isset($this->_running_vars['done_links'])) {
919  $this->_running_vars['done_links'] = Array();
920  }
921 
922  if (!isset($this->_running_vars['link_count'])) {
923  $link_count = 0;
924  foreach ($this->_running_vars['assets'] as $assetid => $links) {
925  $link_count += count($links);
926  }
927  $this->_running_vars['link_count'] = $link_count;
928  }
929 
930  $assets = $this->_running_vars['process_create_links'];
931  $assetid = key($assets);
932  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
933  $links = reset($assets);
934 
935  $value = reset($links);
936  $link_idx = key($links);
937  unset($this->_running_vars['process_create_links'][$assetid][$link_idx]);
938 
939  if ($this->_running_vars['link_action'] == 'create') {
940 
941  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['to_parent_assetid']);
942 
943  if (is_null($new_parent)) {
944  trigger_localised_error('HIPO0023', E_USER_WARNING, $this->_running_vars['to_parent_assetid']);
945  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
946  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
947  return FALSE;
948  }
949 
950  if (is_null($asset)) {
951  trigger_localised_error('HIPO0022', E_USER_WARNING, $assetid);
952  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
953  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
954  return FALSE;
955  }
956 
957  // disallow multiple significant links between the same parent and child
958  // NOTE: failing this will mean that further links (valid or not) will not be processed, in the same
959  // manner as when the new link from $new_parent => $asset isn't created properly (see below)
960  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
961  if ($new_parent->id != $trash_folder->id) {
962  if (($value['link_type'] & SQ_SC_LINK_SIGNIFICANT) && $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($new_parent->id, $asset->id, SQ_SC_LINK_SIGNIFICANT)) {
963  $to_parent_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['to_parent_assetid']);
964  trigger_localised_error('SYS0329', E_USER_WARNING, $asset->name, $asset->id, $to_parent_asset->name, $to_parent_asset->id);
965  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($to_parent_asset);
966  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
967  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
968  return FALSE;
969  }
970  }
971 
972  $step_data['message'] = 'Creating a link between "'.htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET).'" and "'.htmlentities($new_parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET).'".';
973  // Define the value
974  if (isset($this->_running_vars['link_value']) && !empty($this->_running_vars['link_value'])) {
975  $value['value'] = $this->_running_vars['link_value'];
976  } else {
977  $value['value'] = '';
978  }
979 
980  $linkid = $new_parent->createLink($asset, $value['link_type'], $value['value'], $this->_running_vars['to_parent_pos']);
981 
982  if (!$linkid) {
983  trigger_localised_error('HIPO0021', E_USER_WARNING, htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), htmlentities($new_parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
984  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
985  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
986  return FALSE;
987  }
988 
989  $this->_running_vars['to_parent_pos']++;
990  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
991  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
992  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($new_parent);
993  unset($new_parent);
994 
995  // if parent and current asset settings are the same then skip the cascades screen
996  if ($this->_running_vars['can_skip_cascade']) {
997  if (!$this->_canSkipCascadeSteps($assetid, $this->_running_vars['to_parent_assetid'])) {
998  $this->_running_vars['can_skip_cascade'] = FALSE;
999  }
1000  }
1001 
1002  } else if ($this->_running_vars['link_action'] == 'move') {
1003 
1004  $link_info = $GLOBALS['SQ_SYSTEM']->am->getLinkById($value['linkid']);
1005  if ($link_info['locked'] == '1') {
1006  trigger_localised_error('HIPO0087', E_USER_WARNING, $assetid);
1007  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1008  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1009  return FALSE;
1010  }//end if
1011 
1012  // if we are moving to the trash, we want to skip all the steps that ask us if we want
1013  // to cascade permissions, metadata, and workflow. We also need to get all the children
1014  // so the lookups can be updated later
1015  $safe_trash = $GLOBALS['SQ_SYSTEM']->getUserPrefs('user', 'SQ_USER_SAFE_TYPE3_TRASH');
1016  $moving_to_trash = FALSE;
1017  $bridge_id = NULL;
1018 
1019  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
1020  if ($this->_running_vars['to_parent_assetid'] == $trash_folder->id) {
1021  $this->skipStep(3);
1022  $this->skipStep(4);
1023  $this->skipStep(5);
1024  $this->skipStep(6);
1025  $this->skipStep(7);
1026  $this->skipStep(8);
1027 
1028  $moving_to_trash = TRUE;
1029 
1030  $id_parts = explode(':', $assetid);
1031  if (isset($id_parts[1])) $bridge_id = $id_parts[0];
1032 
1033  $children = $GLOBALS['SQ_SYSTEM']->am->getChildren($assetid);
1034 
1035  // If we aren't allowed to trash this, then it's not going
1036  // anywhere, so there's no point running update lookups over
1037  // the children
1038  if (!isset($this->_running_vars['do_not_trash'][$assetid])) {
1039  $this->_running_vars['assets_children'] = array_merge($this->_running_vars['assets_children'], array_keys($children));
1040  }
1041 
1042  // delete links in which the minor is being deleted
1043  $affected_links = array_get_index(array_get_index($this->_running_vars,'affected_links',Array()),$assetid,Array());
1044  foreach ($affected_links as $link) {
1045  // we do not delete the link included in the $value array
1046  // because it will be deleted later on
1047  if ($link['linkid'] !== $value['linkid'] && !$safe_trash) {
1048  $success = $GLOBALS['SQ_SYSTEM']->am->deleteAssetLink($link['linkid'], FALSE);
1049  }
1050  }
1051  }//end if moving to trash
1052 
1053 
1054  // if we are moving a shadow asset to the trash, the bridge is responsible for deletion of links
1055  // and determining whether the shadow asset itself should be deleted
1056  // NOTE: a shadow asset CANNOT be linked to the Trash, therefore it (or the link) must be deleted
1057  if ($moving_to_trash && !is_null($bridge_id)) {
1058 
1059  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById($value['linkid'], $assetid, 'minor');
1060 
1061  // if the major of this link contains no colon, and is not a bridge, then it's a real asset
1062  // with a shadow asset linked underneath, so get the asset manager to handle this delete
1063  if (!empty($link) && (FALSE === strpos($link['majorid'], ':')) && !implements_interface($asset, 'bridge')) {
1064  // if Safe-Trash is enabled, make sure we can delete this link
1065  if (!$safe_trash || ($safe_trash && !in_array($assetid, array_keys($this->_running_vars['do_not_trash'])))) {
1066 
1067  if (!$GLOBALS['SQ_SYSTEM']->am->deleteAssetLink($value['linkid'], FALSE)) {
1068  trigger_localised_error('HIPO0019', E_USER_WARNING, $assetid);
1069  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1070  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1071  return FALSE;
1072  }
1073  }
1074 
1075  } else {
1076  // its a shadow asset linked to a bridge or to another shadow,
1077  // so get the bridge to handle the delete
1078  $bridge = $GLOBALS['SQ_SYSTEM']->am->getAsset($bridge_id);
1079  if (!$safe_trash || ($safe_trash && !in_array($assetid, array_keys($this->_running_vars['do_not_trash'])))) {
1080 
1081  if (!$bridge->deleteAssetLink($value['linkid'])) {
1082  trigger_localised_error('HIPO0019', E_USER_WARNING, $assetid);
1083  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1084  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1085  return FALSE;
1086  }
1087  }
1088  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($bridge);
1089  }
1090  } else {
1091 
1092  $not_to_trash = !$moving_to_trash;
1093  $safe_to_trash = $moving_to_trash && (!$safe_trash || ($safe_trash && !in_array($assetid, array_keys($this->_running_vars['do_not_trash']))));
1094 
1095  // if we are not moving to trash, or this asset is safe to trash, proceed
1096  if ($not_to_trash || $safe_to_trash) {
1097 
1098  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById($value['linkid'], $value['parentid']);
1099  $new_parent_info = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo(Array($this->_running_vars['to_parent_assetid']));
1100 
1101  // disallow multiple significant links between the same parent and child (outside the trash)
1102  // NOTE: failing this will mean that further links (valid or not) will not be processed, in the same
1103  // manner as when moving the link fails (see below)
1104  if ($not_to_trash) {
1105  if (($link['link_type'] & SQ_SC_LINK_SIGNIFICANT) && $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($this->_running_vars['to_parent_assetid'], $asset->id, SQ_SC_LINK_SIGNIFICANT)) {
1106  trigger_localised_error('SYS0329', E_USER_WARNING, $asset->name, $asset->id, $new_parent_info[$this->_running_vars['to_parent_assetid']]['name'], $this->_running_vars['to_parent_assetid']);
1107  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1108  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1109  return FALSE;
1110  }
1111  }
1112 
1113  // if parent and current asset settings are the same then skip the cascades screen
1114  if ($this->_running_vars['can_skip_cascade']) {
1115  if (!$this->_canSkipCascadeSteps($assetid, $this->_running_vars['to_parent_assetid'])) {
1116  $this->_running_vars['can_skip_cascade'] = FALSE;
1117  }
1118  }
1119 
1120  $linkid = $GLOBALS['SQ_SYSTEM']->am->moveLink($value['linkid'], $this->_running_vars['to_parent_assetid'], $link['link_type'], $this->_running_vars['to_parent_pos']);
1121  if (!$linkid) {
1122  trigger_localised_error('HIPO0020', E_USER_WARNING, $assetid, $this->_running_vars['to_parent_assetid']);
1123  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1124  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1125  return FALSE;
1126  }
1127 
1128  $new_link = $GLOBALS['SQ_SYSTEM']->am->getLinkById($linkid);
1129  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($new_link['minorid'], $new_link['minor_type_code']);
1130 
1131  if (is_null($asset)) {
1132  trigger_localised_error('HIPO0019', E_USER_WARNING, $assetid);
1133  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1134  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1135  return FALSE;
1136  }
1137 
1138  $step_data['message'] = translate('hipo_move', htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), htmlentities($new_parent_info[$this->_running_vars['to_parent_assetid']]['name'], ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
1139 
1140  $this->_running_vars['to_parent_pos']++;
1141 
1142  } else {
1143 
1144  // If we are marking for deletion, then do so
1145  if (!$safe_to_trash) {
1146  $cron_manager = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('cron_manager');
1147  $GLOBALS['SQ_SYSTEM']->am->includeAsset('cron_job_attempt_safe_trash');
1148 
1149  if (isset($this->_running_vars['mark_for_deletion'][$asset->id])) {
1150  $link = $GLOBALS['SQ_SYSTEM']->am->getLink($assetid, SQ_LINK_NOTICE, 'cron_job_attempt_safe_trash', TRUE, NULL, 'minor');
1151  if (!$link) {
1152  // Create the cron job
1153  $cron_job = new Cron_Job_Attempt_Safe_Trash();
1154  $cron_job->setAssetToUpdate($asset);
1155 
1156  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
1157  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
1158  if ($cron_manager->addJob($cron_job, $GLOBALS['SQ_SYSTEM']->user)) {
1159  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1160  } else {
1161  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1162  }
1163  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1164 
1165  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($cron_job);
1166  unset($cron_job);
1167  }
1168  }
1169  $step_data['message'] = translate('hipo_creating_safe_trash_job', $asset->id);
1170  } else {
1171  $step_data['message'] = translate('hipo_skipping_asset', $asset->id);
1172  }
1173  }//end else not actually trashing
1174 
1175  }//end else moving to trash
1176 
1177  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1178  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1179 
1180  }//end if create
1181 
1182  if (empty($this->_running_vars['process_create_links'][$assetid])) {
1183  unset($this->_running_vars['process_create_links'][$assetid]);
1184  $this->_running_vars['done_links'][] = $assetid;
1185  }
1186 
1187  if (empty($this->_running_vars['process_create_links'])) {
1188  unset($this->_running_vars['done_links']);
1189  $step_data['percent_done'] = 100;
1190  $step_data['complete'] = TRUE;
1191 
1192  if ($this->_running_vars['can_skip_cascade']) {
1193  $this->skipStep(3);
1194  $this->skipStep(4);
1195  $this->skipStep(5);
1196  $this->skipStep(6);
1197  $this->skipStep(7);
1198  $this->skipStep(8);
1199  }
1200 
1201  } else {
1202  $step_data['percent_done'] = ((count($this->_running_vars['done_links']) * 100) / $this->_running_vars['link_count']);
1203  $step_data['complete'] = FALSE;
1204  }
1205 
1206  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
1207  unset($asset);
1208 
1209  if (count(array_diff(array_keys($this->_running_vars['assets']), array_keys($this->_running_vars['do_not_trash']))) == 0) {
1210  if (empty($this->_running_vars['assets_children'])) {
1211  $this->skipStep(2);
1212  }
1213  }
1214 
1215  return TRUE;
1216 
1217  }//end processCreateLinks()
1218 
1219 
1230  function paintInterface(&$step_data, &$o, $prefix)
1231  {
1232  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1233  if (is_null($hh)) return FALSE;
1234 
1235  $assets = $this->_running_vars['assets'];
1236 
1237  $c = 1;
1238  for (reset($assets); NULL !== ($assetid = key($assets)); next($assets)) {
1239  $o->addHiddenField('link_assetid['.$c.']', $assetid);
1240  $c++;
1241  }
1242 
1243  $o->addHiddenField('link_parentid', $this->_running_vars['to_parent_assetid']);
1244 
1245  $parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['to_parent_assetid']);
1246  if (is_null($parent)) {
1247  trigger_localised_error('HIPO0018', E_USER_WARNING, $this->_running_vars['to_parent_assetid']);
1248  return FALSE;
1249  }
1250 
1251  $o->openSection(translate('note'));
1252  $o->openField('&nbsp;');
1253  $o->addHiddenField('link_completed', '0');
1254 
1255  if (count($this->_running_vars['assets']) > 0) {
1256  if ($this->_running_vars['link_action'] == 'move') {
1257  $success_msg = translate('hipo_asset_move_successful', htmlentities($parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
1258  } else {
1259  $success_msg = translate('hipo_asset_link_successful', htmlentities($parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
1260  }
1261  echo '<p><b>'.$success_msg.'</b></p>';
1262  echo '<ul>';
1263  for (reset($assets); NULL !== ($assetid = key($assets)); next($assets)) {
1264  $asset_info = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo(Array($assetid,));
1265  echo '<li>"'.$asset_info[$assetid]['name'].'"</li>';
1266  }
1267  echo '</ul>';
1268  }
1269 
1270  ?>
1271 
1272  <p><?php echo translate('hipo_permission_workflow_metadata_display', htmlentities($parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)); ?></p>
1273  <p><?php echo translate('hipo_permission_workflow_metadata_cascade_select', htmlentities($parent->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET)); ?></p>
1274  <p><?php echo translate('hipo_permission_workflow_metadata_cascade_none'); ?></p>
1275  <?php
1276  $ei = $parent->getEI();
1277 
1278  $ei->includeStaticScreen('permissions');
1279  $pe = paintInlinePermissions($parent, $o, $ei);
1280 
1281  $ei->includeStaticScreen('workflow');
1282  $wf = paintInlineWorkflow($parent, $o, $ei);
1283 
1284  $ei->includeStaticScreen('metadataSchemas');
1285  $ms = paintInlineMetadataSchemas($parent, $o, $ei);
1286 
1287  $ei->includeStaticScreen('tagging');
1288  $ta = paintInlineTagging($parent, $o, $ei);
1289 
1290  $ei->includeStaticScreen('roles');
1291  $ro = paintInlineRoles($parent, $o, $ei);
1292 
1293  $o->addHiddenField('form_submitted', 1);
1294  $o->closeField();
1295  $o->closeSection();
1296 
1297  $o->openSection(translate('cascade'));
1298  $o->openField('', 'cascade');
1299  echo ($pe) ? translate('permissions').' '.check_box('cascade[]', 'cascade_pe').'<br />' : '';
1300  echo ($ms) ? translate('metadata_schemas').' '.check_box('cascade[]', 'cascade_ms').'<br />' : '';
1301  echo ($wf) ? translate('workflow').' '.check_box('cascade[]', 'cascade_wf').'<br />' : '';
1302  echo ($ta) ? translate('content_tags').' '.check_box('cascade[]', 'cascade_ta').'<br />' : '';
1303  echo ($ro) ? translate('roles').' '.check_box('cascade[]', 'cascade_ro').'<br />' : '';
1304  $o->closeField();
1305  $o->closeSection();
1306 
1307  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($parent);
1308  unset($parent);
1309 
1310  return TRUE;
1311 
1312  }//end paintInterface()
1313 
1314 
1324  function processInterface(&$step_data, $prefix)
1325  {
1326  // has the next button been clicked ?
1327  if (isset($_REQUEST['form_submitted'])) {
1328  if (isset($_REQUEST['cascade'])) {
1329  // permissions
1330  if (!in_array('cascade_pe', $_REQUEST['cascade'])) {
1331  $this->skipStep(4);
1332  }
1333  // metadata
1334  if (!in_array('cascade_ms', $_REQUEST['cascade'])) {
1335  $this->skipStep(5);
1336  }
1337  // workflow
1338  if (!in_array('cascade_wf', $_REQUEST['cascade'])) {
1339  $this->skipStep(6);
1340  }
1341  // tags
1342  if (!in_array('cascade_ta', $_REQUEST['cascade'])) {
1343  $this->skipStep(7);
1344  }
1345  // roles
1346  if (!in_array('cascade_ro', $_REQUEST['cascade'])) {
1347  $this->skipStep(8);
1348  }
1349  } else {
1350  $this->skipStep(4); // permissions
1351  $this->skipStep(5); // metadata
1352  $this->skipStep(6); // workflow
1353  $this->skipStep(7); // tags
1354  $this->skipStep(8); // roles
1355  }
1356  $step_data['percent_done'] = 100;
1357  $step_data['complete'] = TRUE;
1358  }//end if
1359 
1360  return TRUE;
1361 
1362  }//end processInterface()
1363 
1364 
1375  function _canSkipCascadeSteps($assetid, $parentid)
1376  {
1377  // Permissions
1378  $perms = Array('Read' => SQ_PERMISSION_READ, 'Write' => SQ_PERMISSION_WRITE, 'Administrator' => SQ_PERMISSION_ADMIN);
1379  foreach ($perms as $title => $perm) {
1380  $permissions = $GLOBALS['SQ_SYSTEM']->am->getAssetPermissionByCascade($assetid, $perm, NULL, NULL);
1381  $ppermissions = $GLOBALS['SQ_SYSTEM']->am->getAssetPermissionByCascade($parentid, $perm, NULL, TRUE);
1382  $diff = array_diff_assoc($ppermissions, $permissions);
1383  if (!empty($diff)) return FALSE;
1384  }
1385 
1386  // Workflow Schemas
1387  $wfm = $GLOBALS['SQ_SYSTEM']->getWorkflowManager();
1388  $schemas = $wfm->getSchemas($assetid, NULL, NULL);
1389  $pschemas = $wfm->getSchemas($parentid, NULL, TRUE);
1390  $diff = array_diff_assoc($pschemas, $schemas);
1391  if (!empty($diff)) return FALSE;
1392 
1393  // Metadata Schemas
1394  // Compare all schemas applied with the cascadable schemas of the parent
1395  $mm = $GLOBALS['SQ_SYSTEM']->getMetadataManager();
1396  $schemas = $mm->getSchemas($assetid, NULL, NULL);
1397  $pschemas = $mm->getSchemas($parentid, NULL, TRUE);
1398  $diff = array_diff_assoc($pschemas, $schemas);
1399  if (!empty($diff)) return FALSE;
1400 
1401  // Tag links
1402  $tag_manager = $GLOBALS['SQ_SYSTEM']->getTagManager();
1403  $tls = $tag_manager->getTagLinks($assetid);
1404  $ptls = $tag_manager->getTagLinks($parentid);
1405 
1406  $num_ptls = count($ptls);
1407  if ($num_ptls != 0) {
1408  if ($num_ptls == count($tls)) {
1409  foreach ($ptls as $pkey => $plink_details) {
1410  $tag_found = FALSE;
1411  foreach ($tls as $tkey => $tlink_details) {
1412  if ($plink_details['minorid'] == $tlink_details['minorid']) {
1413  $tag_found = TRUE;
1414  }
1415  }
1416  if (!$tag_found) return FALSE;
1417  }
1418  } else {
1419  return FALSE;
1420  }
1421  }
1422 
1423  // Roles
1424  $roles = $GLOBALS['SQ_SYSTEM']->am->getRole($assetid);
1425  $proles = $GLOBALS['SQ_SYSTEM']->am->getRole($parentid);
1426  $diff = array_diff_assoc($proles, $roles);
1427  if (!empty($diff)) return FALSE;
1428 
1429  return TRUE;
1430 
1431  }//end _canSkipCascadeSteps()
1432 
1433 
1447  function updateLookups(&$job_type, &$running_vars, &$options)
1448  {
1449  $job_type = 'hipo_job_update_lookups';
1450  $options['auto_complete'] = TRUE;
1451 
1452  $assetids = Array();
1453  $assets = $this->_running_vars['assets'];
1454  for (reset($assets); NULL !== ($assetid = key($assets)); next($assets)) {
1455  if (!isset($this->_running_vars['do_not_trash'][$assetid])) {
1456  $assetids[] = $assetid;
1457  }
1458  }
1459 
1460  if (!empty($this->_running_vars['assets_children'])) {
1461  $assetids = array_merge($assetids, $this->_running_vars['assets_children']);
1462  }
1463 
1464  $running_vars['assetids'] = $assetids;
1465 
1466  }//end updateLookups()
1467 
1468 
1479  function cascadePermissions(&$job_type, &$running_vars, &$options)
1480  {
1481  $job_type = 'hipo_job_edit_permissions';
1482  $permission_vars = Array();
1483 
1484  foreach (Array(SQ_PERMISSION_READ, SQ_PERMISSION_WRITE, SQ_PERMISSION_ADMIN) as $perm) {
1485  $set_perms = $GLOBALS['SQ_SYSTEM']->am->getAssetPermissionByCascade($this->_running_vars['to_parent_assetid'], $perm, NULL, TRUE);
1486 
1487  foreach ($set_perms as $userid => $perm_data) {
1488  $permission_vars[] = Array(
1489  'permission' => $perm,
1490  'granted' => $perm_data['granted'],
1491  'userid' => $perm_data['userid'],
1492  'previous_access' => NULL,
1493  'assetids' => array_keys($this->_running_vars['assets']),
1494  'cascades' => TRUE,
1495  );
1496  }
1497  }
1498 
1499  $running_vars['permission_changes'] = $permission_vars;
1500 
1501  }//end cascadePermissions()
1502 
1503 
1514  function cascadeMetadata(&$job_type, &$running_vars, &$options)
1515  {
1516  $job_type = 'hipo_job_edit_metadata_schemas';
1517  $mm = $GLOBALS['SQ_SYSTEM']->getMetadataManager();
1518  $schemas = $mm->getSchemas($this->_running_vars['to_parent_assetid'], NULL, TRUE);
1519  $schema_vars = Array();
1520 
1521  foreach ($schemas as $schemaid => $granted) {
1522  $schema_vars[] = Array(
1523  'assetids' => array_keys($this->_running_vars['assets']),
1524  'granted' => $granted,
1525  'schemaid' => $schemaid,
1526  'cascades' => TRUE,
1527  'previous_access' => NULL,
1528  );
1529  }
1530  $running_vars['schema_changes'] = $schema_vars;
1531  $running_vars['assets'] = $this->_running_vars['assets'];
1532 
1533  }//end cascadeMetadata()
1534 
1535 
1546  function cascadeWorkflow(&$job_type, &$running_vars, &$options)
1547  {
1548  $job_type = 'hipo_job_edit_workflow_schemas';
1549  $wfm = $GLOBALS['SQ_SYSTEM']->getWorkflowManager();
1550  $schemas = $wfm->getSchemas($this->_running_vars['to_parent_assetid'], NULL, FALSE, TRUE);
1551  $schema_vars = Array();
1552 
1553  foreach ($schemas as $schemaid => $granted) {
1554  $schema_vars[] = Array(
1555  'assetids' => array_keys($this->_running_vars['assets']),
1556  'granted' => $granted,
1557  'schemaid' => $schemaid,
1558  'cascades' => TRUE,
1559  'previous_access' => NULL,
1560  );
1561  }
1562  $running_vars['schema_changes'] = $schema_vars;
1563 
1564  }//end cascadeWorkflow()
1565 
1566 
1577  function cascadeTags(&$job_type, &$running_vars, &$options)
1578  {
1579  $job_type = 'hipo_job_edit_tags';
1580  $tag_manager = $GLOBALS['SQ_SYSTEM']->getTagManager();
1581  $current_tag_links = $tag_manager->getTagLinks($this->_running_vars['to_parent_assetid']);
1582  $tag_vars = Array();
1583 
1584  foreach ($current_tag_links as $link) {
1585  $tag_vars[] = Array(
1586  'tag_id' => $link['minorid'],
1587  'action' => 'add',
1588  'weight' => $link['value'],
1589  );
1590  }
1591 
1592  $running_vars['tag_changes'] = $tag_vars;
1593  $running_vars['assets'] = $this->_running_vars['assets'];
1594 
1595  }//end cascadeTags()
1596 
1597 
1608  function cascadeRoles(&$job_type, &$running_vars, &$options)
1609  {
1610  $job_type = 'hipo_job_edit_roles';
1611  $roles = $GLOBALS['SQ_SYSTEM']->am->getRole($this->_running_vars['to_parent_assetid']);
1612  $roles_vars = Array();
1613 
1614  foreach ($roles as $roleid => $users) {
1615  $role_vars['add'][$roleid] = $users;
1616  }
1617  $running_vars['role_changes'] = $role_vars;
1618  $running_vars['assets'] = $this->_running_vars['assets'];
1619 
1620 
1621  }//end cascadeRoles()
1622 
1623 
1634  function paintRefresh(&$step_data, &$o, $prefix)
1635  {
1636  // Only process in the later steps (otherwise it performs a double 'get_assets' request to the asset map)
1637  if ($step_data['percent_done'] > 0) {
1638  $o->addOnLoad('if (window.opener.parent.frames["sq_sidenav"] && window.opener.parent.frames["sq_sidenav"].reload_asset) window.opener.parent.frames["sq_sidenav"].reload_asset("'.$this->_running_vars['to_parent_assetid'].'");');
1639 
1640  $refreshids = Array();
1641 
1642  foreach ($this->_running_vars['assets'] as $links) {
1643  foreach ($links as $link) {
1644  $refreshids[] = $link['parentid'];
1645  }
1646  }
1647  $refreshids = array_unique($refreshids);
1648 
1649  foreach ($refreshids as $refreshid) {
1650  $o->addOnLoad('if (window.opener.parent.frames["sq_sidenav"] && window.opener.parent.frames["sq_sidenav"].reload_asset) window.opener.parent.frames["sq_sidenav"].reload_asset("'.$refreshid.'");');
1651  }
1652  }//end if
1653 
1654  return TRUE;
1655 
1656  }//end paintRefresh()
1657 
1658 
1668  function processRefresh(&$step_data, $prefix)
1669  {
1670  if ($step_data['percent_done'] == 0) {
1671  $step_data['percent_done'] = 50;
1672  } else {
1673  $step_data['percent_done'] = 100;
1674  $step_data['complete'] = TRUE;
1675  }
1676 
1677  return TRUE;
1678 
1679  }//end processRefresh()
1680 
1681 
1688  function freestyle()
1689  {
1690  $step_data = Array();
1691  $this->_running_vars['can_skip_cascade'] = FALSE;
1692 
1693  // process confirmation
1694  $result = TRUE;
1695  while ($result && !array_get_index($step_data, 'complete')) {
1696  $result = $this->processCreateLinks($step_data, '');
1697  }
1698  if (!$result) {
1699  $this->_addError('creating links failed');
1700  return FALSE;
1701  }
1702 
1703  // update lookups
1704  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1705  $vars = Array('assetids' => array_keys($this->_running_vars['assets']));
1706 
1707  $lookup_errors = $hh->freestyleHipo('hipo_job_update_lookups', $vars);
1708  if (!empty($lookup_errors)) {
1709  $this->_addError('hipo_job_update_lookups failed');
1710  return FALSE;
1711  }
1712 
1713  // process cascading options
1714  $cascading_list = Array(
1715  'cascadePermissions' => 'cascade_pe',
1716  'cascadeMetadata' => 'cascade_ms',
1717  'cascadeWorkflow' => 'cascade_wf',
1718  'cascadeTags' => 'cascade_ta',
1719  );
1720 
1721  foreach ($cascading_list as $fn_name => $value) {
1722  $job_type = '';
1723  $running_vars = Array();
1724  $options = '';
1725 
1726  if (isset($this->_running_vars[$value]) && $this->_running_vars[$value]) {
1727  $this->$fn_name($job_type, $running_vars, $options);
1728  $errors = $hh->freestyleHipo($job_type, $running_vars);
1729  }
1730 
1731  if (!empty($errors)) {
1732  $this->_addError('error occured during '.$fn_name);
1733  return FALSE;
1734  }
1735 
1736  }//end foreach
1737 
1738  return TRUE;
1739 
1740  }//end freestyle()
1741 
1742 
1743 }//end class
1744 
1745 ?>