Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
asset_map.inc
1 <?php
30 class Asset_Map
31 {
32 
33 
38  function Asset_Map()
39  {
40 
41  }//end constructor
42 
43 
52  function paint(&$backend)
53  {
54  $backend->out->addJsInclude(sq_web_path('lib').'/asset_map/asset_map.js');
55 
56  ?>
57  <script type="text/javascript"><!--
58  //<![CDATA[
59  init_asset_map();
60  //]]> -->
61  </script>
62 
63  <table style="height: 100%; width: 100%;">
64  <tr>
65  <td class="sq-backend-header-item" style="width: 100%;"><img style="margin-left: 7px;" src="<?php echo sq_web_path('lib'); ?>/web/images/icons/asset_map/matrix_logo.gif" alt="MySource Matrix" /></td>
66  </tr>
67  <tr>
68  <td style="height: 100%; width: 100%;" valign="top">
69  <?php
70  $this->embedAssetMap('complex', '224');
71  ?>
72  </td>
73  </tr>
74  </table>
75  <?php
76 
77  }//end paint()
78 
79 
89  function _findCommonParentId($assetid1, $assetid2)
90  {
91  if (!isset($assetid2) || empty($assetid2) || $assetid1 == $assetid2) {
92  return $assetid1;
93  }
94 
95  $lineages1 = $GLOBALS['SQ_SYSTEM']->am->getLinkLineages($assetid1);
96 
97  $lineages2 = $GLOBALS['SQ_SYSTEM']->am->getLinkLineages($assetid2);
98 
99  if (empty($lineages1) && !empty($lineages2)) {
100  return $assetid2;
101  } else if (!empty($lineages1) && empty($lineages2)) {
102  return $assetid1;
103  }
104 
105  $common_lineage = Array();
106  foreach ($lineages1 as $lineage) {
107  $lineageids = array_keys($lineage['lineage']);
108  if ($lineageids[0] == 1) array_shift($lineageids);
109  $lineageids[] = $assetid1;
110  foreach ($lineages2 as $lineage2) {
111  $lineage2ids = array_keys($lineage2['lineage']);
112  if ($lineage2ids[0] == 1) array_shift($lineage2ids);
113  $lineage2ids[] = $assetid2;
114  $intersected = array_intersect($lineageids, $lineage2ids);
115  if (count($intersected) > count($common_lineage)) {
116  $common_lineage = $intersected;
117  }
118  }
119  }
120 
121  if (empty($common_lineage)) return 1;
122 
123  return array_pop($common_lineage);
124 
125  }//end _findCommonParentId()
126 
127 
136  function _findCommonRoot($assetids)
137  {
138  $count = count($assetids);
139  // if we have only 1 asset then thats the common root
140  if ($count == 1) return $assetids[0];
141 
142  $parentid = $assetids[0];
143  for ($i=0; $i<$count; $i++) {
144  if ($i == $count-1) {
145  $compare_to = 0;
146  } else {
147  $compare_to = $assetids[$i+1];
148  }
149  $parentid = $this->_findCommonParentId($parentid, $compare_to);
150  if ($parentid == 1) break;
151  }
152 
153  return $parentid;
154 
155  }//end _findCommonRoot()
156 
157 
168  function _getInitialLineageSelection($type='')
169  {
170 
171  $initial_selection_lineage = '';
172  $asset = $GLOBALS['SQ_SYSTEM']->am->getAssetFromURL(NULL, NULL, TRUE, TRUE);
173 
174  if (!is_null($asset) && !empty($asset)) {
175 
176  // get assets lineage info
177  $asset_lineage = $GLOBALS['SQ_SYSTEM']->am->getLineageFromURL();
178  $asset_link_lineage = $GLOBALS['SQ_SYSTEM']->am->getLinkLineages($asset->id);
179 
180  $assetids = '';
181  $sort_orders = '';
182  $sort_orders_append = '';
183 
184  $db = MatrixDAL::getDb();
185 
186  $num_assets = count($asset_lineage);
187  for ($i=0; $i < $num_assets; $i++) {
188 
189  if (!($asset_lineage[$i]['link_type'] & (SQ_LINK_TYPE_1 | SQ_LINK_TYPE_2))) {
190  continue;
191  }
192 
193  if ($i == 0) {
194  $previd = 1;
195  } else {
196  $previd = $asset_lineage[$i-1]['assetid'];
197  }
198  $currentid = $asset_lineage[$i]['assetid'];
199 
200  $assetids .= $currentid.'|';
201 
202  // get the sort orders for each link
203  $sql = 'SELECT l.sort_order FROM sq_ast_lnk l
204  INNER JOIN sq_ast_lookup u ON l.minorid = u.assetid
205  WHERE l.majorid = :previd
206  AND l.minorid = :currentid
207  AND u.url = :url';
208 
209  try {
210  $query = MatrixDAL::preparePdoQuery($sql);
211  MatrixDAL::bindValueToPdo($query, 'previd', $previd);
212  MatrixDAL::bindValueToPdo($query, 'currentid', $currentid);
213  MatrixDAL::bindValueToPdo($query, 'url', $asset_lineage[$i]['url']);
214  $sort_order = MatrixDAL::executePdoOne($query);
215  } catch (Exception $e) {
216  throw new Exception('Unable to get the sort orders for URL: '.$asset_lineage[$i]['url'].' due to database error: '.$e->getMessage());
217  }
218 
219  // Bug #3108
220  // No sort order found here - because the site exists under a folder (under the root folder)
221  // Excution stops here because an exception is caught by an empty sort order
222  if (!empty($sort_order)) {
223  // adjust real sort order for links that are not visible on nav
224  $sql = 'SELECT count(*) FROM sq_ast_lnk
225  WHERE majorid = :previd
226  AND sort_order < :sort_order
227  AND link_type > 2';
228  try {
229  $query = MatrixDAL::preparePdoQuery($sql);
230  MatrixDAL::bindValueToPdo($query, 'previd', $previd, PDO::PARAM_STR);
231  MatrixDAL::bindValueToPdo($query, 'sort_order', $sort_order, PDO::PARAM_INT);
232  $count = MatrixDAL::executePdoOne($query);
233  } catch (Exception $e) {
234  throw new Exception('Unable to adjust real sort order for majorid: '.$previd.' due to database error: '.$e->getMessage());
235  }
236  if ($count > 0) $sort_order = $sort_order - $count;
237  }//end if
238  $sort_orders .= $sort_order.'|';
239  }//end for
240 
241  $assetid_lineage = Array();
242  foreach ($asset_lineage as $lineage) {
243  $assetid_lineage[] = $lineage['assetid'];
244  }
245 
246  // The last asset id here is the current asset. It won't be in the link lineage.
247  array_pop($assetid_lineage);
248 
249  $cur_lineage_num = 0;
250  foreach ($asset_link_lineage as $lineage_num => $lineage_info) {
251  // Use the first link lineage that completly encapsulates the URL lineage.
252  $diff = array_diff($assetid_lineage, array_keys($lineage_info['lineage']));
253  if (empty($diff)) {
254  $cur_lineage_num = $lineage_num;
255  break;
256  }
257  }
258 
259  // Do we have any other assets between the root and the site?
260  $num_site_parents = 0;
261  $tmp_assetids = '';
262  $site_found = FALSE;
263  if ($num_assets > 0 && !empty($asset_link_lineage[$cur_lineage_num]['lineage'])) {
264  foreach ($asset_link_lineage[$cur_lineage_num]['lineage'] as $assetid => $asset_name) {
265  if ((int)$assetid != 1 && $asset_lineage[0]['assetid'] != $assetid) {
266  $tmp_assetids .= $assetid.'|';
267  $num_site_parents++;
268  } else {
269  $site_found = TRUE;
270  break;
271  }
272  }
273  }
274 
275  // Asset link lineage does not have the site asset, but are we looking after the site itself?
276  if (!$site_found) {
277  if ($num_assets == 1) {
278  $site_found = TRUE;
279  $asset_link_lineage[$cur_lineage_num]['lineage'][$asset_lineage[0]['assetid']] = $asset_lineage[0]['name'];
280  }
281  }
282 
283  // Ok, this site is under other assets. The assetmap wouldn't find the location
284  // unless we fix it
285  if ($site_found && $num_site_parents > 0) {
286  $assetids = $tmp_assetids.$assetids;
287 
288  // Add sort order but do not join with lookup table
289  $i = 0;
290  foreach ($asset_link_lineage[$cur_lineage_num]['lineage'] as $assetid => $asset_name) {
291  if ($i == $num_site_parents + 1) break;
292 
293  $previd = (string) $currentid;
294  if ($i == 0) $previd = '1';
295  $currentid = $assetid;
296 
297  try {
298  $bind_vars = Array (
299  'majorid' => $previd,
300  'minorid' => $currentid,
301  );
302  $sort_order = MatrixDAL::executeOne('core', 'getSortOrder', $bind_vars);
303  } catch (Exception $e) {
304  throw new Exception('Unable to get sort order for majorid: '.$previd.' and minorid: '.$currentid.' due to database error: '. $e->getMessage());
305  }
306  $sort_orders_append .= '|'.$sort_order;
307  $i++;
308  }
309  }
310  $sort_orders = $sort_orders_append.$sort_orders; //Bug #4413 Fix
311  $assetids = trim($assetids, '|');
312  $sort_orders = trim($sort_orders, '|');
313 
314  $initial_selection_lineage = $assetids.'~'.$sort_orders;
315  } else if (strtolower($type) == 'simple') {
316  // Check the cookies
317  if (isset($_COOKIE['lastSelectedAssetId']) && isset($_COOKIE['lastSelectedLinkId'])) {
318  $link_lineages = $GLOBALS['SQ_SYSTEM']->am->getLinkLineages($_COOKIE['lastSelectedAssetId']);
319  $id_parts = explode(':', $_COOKIE['lastSelectedAssetId']);
320  foreach ($link_lineages as $lineage) {
321  if ($lineage['linkid'] == $_COOKIE['lastSelectedLinkId'] || (($lineage['link_type'] & SQ_SC_LINK_BACKEND_NAV) && isset($id_parts[1]))) {
322  $asset_lineage = array_keys($lineage['lineage']);
323  $assetids = '';
324  $sort_orders = '';
325 
326  $asset_lineage[] = $_COOKIE['lastSelectedAssetId'];
327  $num_assets = count($asset_lineage);
328  for ($i=0; $i < $num_assets; $i++) {
329  if ($i == 0) {
330  $previd = 1;
331  } else {
332  $previd = $asset_lineage[$i-1];
333  }
334 
335  if ($asset_lineage[$i] == 1) continue;
336  $assetids .= $asset_lineage[$i].'|';
337  $sort_orders .= '-1|';
338  }//end for
339 
340  $assetids = trim($assetids, '|');
341  $sort_orders = trim($sort_orders, '|');
342  $initial_selection_lineage = $assetids.'~'.$sort_orders;
343  break;
344  }
345  }
346  }
347  }//end if
348 
349  return $initial_selection_lineage;
350 
351  }//end _getInitialLineageSelection()
352 
353 
371  function embedAssetMap($type='simple', $width=200, $height=0)
372  {
373  $classname = '';
374  $jarname = '';
375 
376  // notice that the package name (the directory) should be the same as the jar name, so no need for
377  // another variable
378 
379  // create some vars to what jar file to include, and also the class name in the jar
380  // that has the main function
381  switch (strtolower($type)) {
382  case 'simple':
383  $classname = 'SimpleAssetMap';
384  $jarname = 'assetmap';
385  if (!defined('SQ_PAINTED_SIMPLE_ASSET_MAP')) {
386  define('SQ_PAINTED_SIMPLE_ASSET_MAP', TRUE);
387  }
388  break;
389  case 'complex':
390  $classname = 'AssetMap';
391  $jarname = 'complexassetmap';
392  break;
393  }
394 
395  $root_url = sq_web_path('root_url');
396  if ($root_url{strlen($root_url) - 1} != '/') {
397  $root_url = $root_url.'/';
398  }
399 
400  // we want to use current_url()
401  require_once SQ_INCLUDE_PATH.'/general.inc';
402  ?>
403  <script type="text/javascript" src="<?php echo sq_web_path('lib').'/js/detect.js' ?>"></script>
404  <script type="text/javascript" src="<?php echo sq_web_path('fudge').'/var_serialise/var_serialise.js' ?>"></script>
405  <script type="text/javascript" src="<?php echo sq_web_path('lib').'/asset_map/asset_map.js';?>"></script>
406 
407  <?php
408  ob_start();
409  if (isset($GLOBALS['SQ_SYSTEM']->user)) {
410  $user = $GLOBALS['SQ_SYSTEM']->user;
411  } else {
412  $user = NULL;
413  }//end if
414 
415  // Check for at least simple edit access
416  if (is_null($user) || $user instanceof Public_User || (method_exists($user, 'canAccessBackend') && !($user instanceof Simple_Edit_User || $user->canAccessBackend()))) {
417  ?>
418  <b>You need Simple Edit access or higher to view the Asset Map</b>
419  <?php
420  } else {
421  ?>
422  <applet id="sq_asset_map" width="<?php echo $width; ?>" height="%applet_height%" code="net/squiz/matrix/<?php echo ($type == 'simple') ? $jarname : 'assetmap'; ?>/<?php echo $classname; ?>.class" archive="<?php echo sq_web_path('lib'); ?>/asset_map/java/<?php echo $jarname; ?>.jar?t=<?php echo time(); ?>" MAYSCRIPT>
423 
424  <?php
425 
426  $prefs = $GLOBALS['SQ_SYSTEM']->getUserPrefs('user', 'SQ_USER_ASSET_MAP_LINEAGE');
427 
428  $assetids = explode(',',$prefs);
429  $rootlineage = '';
430 
431  $common_parentid = $this->_findCommonRoot($assetids);
432 
433  if (!empty($common_parentid)) {
434  $lineages = $GLOBALS['SQ_SYSTEM']->am->getLinkLineages($common_parentid);
435 
436  // Find the first SQ_SC_LINK_BACKEND_NAV, rather than simply getting it from the beginning
437  $first_lineage = Array();
438  if (!empty($lineages)) {
439  foreach ($lineages as $lineage) {
440  if ((int) $lineage['link_type'] & SQ_SC_LINK_BACKEND_NAV) {
441  $first_lineage = $lineage;
442  break;
443  }
444  }
445  }
446 
447  if (!empty($first_lineage)) {
448  $lineage_assetids = array_keys($first_lineage['lineage']);
449  $lineage_assetids[] = $common_parentid;
450  $rootlineage = get_asset_lineage_sort_order($lineage_assetids);
451 
452  // Initial Lineage Selection will be disabled if the Root Node is set for the user
453  // Simply asset map does not work for this option
454  $initial_selection_lineage = '';
455  }
456  }
457 
458  if (empty($rootlineage)) {
459  // Initial lineage selection (i.e ..com/site1/blah/_admin will expand the lineage of that asset)
460  $initial_selection_lineage = $this->_getInitialLineageSelection($type);
461  }
462 
463  $parameters = Array(
464  'parameter.backendsuffix' => SQ_CONF_BACKEND_SUFFIX,
465  'parameter.sessionid' => $_COOKIE['SQ_SYSTEM_SESSION'],
466  'parameter.sessionkey' => $GLOBALS['SQ_SYSTEM']->getUniqueSessionKey(),
467  'parameter.url.iconurl' => '__lib/web/images/icons',
468  'parameter.url.typecodeurl' => '__data/asset_types',
469  'parameter.url.notaccessibleicon' => 'asset_map/not_accessible.png',
470  'parameter.url.type2icon' => 'asset_map/not_visible.png',
471  'parameter.url.assetmapiconurl' => '__lib/web/images/icons/asset_map',
472  'parameter.url.baseurl' => $root_url,
473  'parameter.url.execurl' => $root_url.SQ_CONF_BACKEND_SUFFIX.'?SQ_ACTION=asset_map_request&SESSION_ID='.$_COOKIE['SQ_SYSTEM_SESSION'].'&SESSION_KEY='.$GLOBALS['SQ_SYSTEM']->getUniqueSessionKey(),
474  'parameter.asset.limit' => SQ_CONF_ASSET_MAP_ASSET_LIMIT,
475  'parameter.java.supportedversion' => '1.4.2,1.5.0,1.6.0',
476  'parameter.java.sunurl' => 'http://java.sun.com/webapps/getjava/BrowserRedirect?locale=en&host=www.java.com:80',
477  'parameter.rootlineage' => $rootlineage,
478  'parameter.initialselection' => $initial_selection_lineage,
479  );
480 
481  // this is important because it tells the asset map what the available
482  // paramters are so that it can load them without explicitly knowing the names
483  $params = implode(',', array_keys($parameters));
484  ?><param name="parameter.params" value="<?php echo $params; ?>" /><?php
485 
486  foreach ($parameters as $parameter => $value) {
487  ?><param name="<?php echo $parameter; ?>" value="<?php echo $value; ?>" /><?php
488  }
489 
490  echo '<p class="sq-backend-header-item" style="margin: 10px;">';
491  echo translate('asset_map_error_jre_latest_version_msg', '<a class="sq-backend-header-item" style="text-decoration: underline" href="http://java.sun.com/webapps/getjava/BrowserRedirect?locale=en&host=www.java.com:80" target="_blank">Java Runtime Environment</a>');
492  echo '</p>';
493  ?>
494  </applet>
495  <?php
496  }//end if
497  $applet_tag = ob_get_contents();
498  ob_end_clean();
499 
500  if ($height <= 0) {
501  $height = "' + (document.body.offsetHeight - ".(SQ_IN_LIMBO ? 51 : 70).") + '";
502  $applet_tag = str_replace("\n", ' ', $applet_tag);
503  ?>
504  <script type="text/javascript"><!--
505  //<![CDATA[
506  document.write('<?php echo str_replace('%applet_height%', $height, $applet_tag); ?>');
507  //]]> -->
508  </script>
509  <?php
510  } else {
511  echo str_replace('%applet_height%', $height, $applet_tag);
512  }
513 
514  }//end embedAssetMap()
515 
516 
525  function _send($output)
526  {
527  header('Content-Type: text/xml; encoding=utf-8');
528  echo $output->asXML();
529 
530  }//end _send()
531 
532 
541  function _error($code)
542  {
543  // if second parameter is an array, use that as our list of params
544  // otherwise, everything after 1st param is our list of params that we
545  // will pump into the error, sprintf() style
546  if (func_num_args() == 1) {
547  $func_args = Array();
548  } else if (!is_array($func_args = func_get_arg(1))) {
549  $func_args = func_get_args();
550  $func_args = array_slice($func_args,1);
551  }
552 
553  $output = simplexml_load_string('<xml></xml>');
554  $responses = $output->addChild('error', $GLOBALS['SQ_SYSTEM']->lm->getErrorMessage($code, $func_args));
555  /* XML output
556  <?xml version="1.0"?>
557  <error>Unable to Move Asset, Link #64 not found [AMAP0032]</error>
558  */
559  $this->_send($responses);
560  exit();
561 
562  }//end _error()
563 
564 
573  function process(&$backend)
574  {
575  ini_set("display_errors", 0);
576 
577  // block public users from probing
578  $user = isset($GLOBALS['SQ_SYSTEM']->user) ? $GLOBALS['SQ_SYSTEM']->user : NULL;
579  if (is_null($user) || $user instanceof Public_User || (method_exists($user, 'canAccessBackend') && !($user instanceof Simple_Edit_User || $user->canAccessBackend() || (method_exists($user, 'isShadowSimpleEditUser') && $user->isShadowSimpleEditUser())))) {
580  exit();
581  }
582 
583  // set the output type to XML, so any errors raised by the objects will be sent along in XML
584  $GLOBALS['SQ_OUTPUT_TYPE'] = 'xml';
585 
586  require_once SQ_FUDGE_PATH.'/general/file_system.inc';
587 
588  $xml = file_get_contents("php://input");
589  // disable loading external entitties to prevent scanning for file existence
590  if (function_exists('libxml_disable_entity_loader'))
591  libxml_disable_entity_loader(TRUE);
592  $root = simplexml_load_string($xml);
593  if (function_exists('libxml_disable_entity_loader'))
594  libxml_disable_entity_loader(FALSE);
595 
596  switch ($root['action']) {
597  case 'get translations' :
598  $this->_getTranslations($input);
599  break;
600  case 'initialise' :
601  $this->_doInitialise();
602  break;
603  case 'get assets' :
604  $this->_getAssets($root);
605  break;
606  case 'get url' :
607  $this->_getURL($root, $backend);
608  break;
609  case 'clone' :
610  $this->_cloneAssets($root, $backend);
611  break;
612  case 'move asset' :
613  $this->_moveAssets($root, $backend);
614  break;
615  case 'new link' :
616  $this->_newLinks($root);
617  break;
618  default :
619  $this->_error('AMAP0003', (string)$root->attributes()->action);
620  return;
621  }
622 
623 
624  }//end process()
625 
626 
635  function _getTranslations(&$input)
636  {
637  $current_locale = $GLOBALS['SQ_SYSTEM']->lm->getCurrentLocale();
638 
639  header('Content-Type: text/xml');
640  ob_start();
641  echo '<translations locale="'.$current_locale.'">'."\n";
642  echo "<![CDATA[\n";
643  $locales = $GLOBALS['SQ_SYSTEM']->lm->getCumulativeLocaleParts($current_locale);
644  foreach ($locales as $locale) {
645  $file_name = SQ_DATA_PATH.'/private/system/core/java_strings_'.$locale.'.properties';
646  if (file_exists($file_name)) {
647  echo file_get_contents($file_name)."\n\n";
648  }
649  }
650  echo ']]>';
651  echo "</translations>\n";
652  $out = ob_get_contents();
653  ob_end_clean();
654 
655  echo $out;
656 
657  }//end _getTranslations()
658 
659 
668  function _doInitialise()
669  {
670 
671  $output = simplexml_load_string('<xml></xml>');
672  $current_user = $GLOBALS['SQ_SYSTEM']->user;
673 
674  // get the current user and its dependants (inbox and workspace)
675  // so the asset map can create a java object for each
676  $current_user_info = $this->_getAssetInfo($current_user->id);
677 
678  $root = $output->addChild('root');
679  $current_user_node = $root->addChild('current_user');
680  foreach ($current_user_info as $key => $value) {
681  if (strlen($value) == 0) $current_user_node->addAttribute($key, ' ');
682  else $current_user_node->addAttribute($key, $value);
683  }
684 
685  $current_user_node_info = $current_user_node->addChild('asset');
686  $this->_getChildAssets($current_user_node_info, $current_user->id, TRUE, TRUE);
687  $current_user_xml = $current_user_node->asXML();
688 
689  // get info and children for the root folder
690  // note the hard code the assetid of the root folder because
691  // it MUST ALWAYS be the first asset created
692  $assets_node = $root->addChild('assets');
693  $info = $this->_getAssetInfo('1');
694  $root_node_info = $assets_node->addChild('asset');
695  foreach ($info as $key => $value) {
696  if (strlen($value) == 0) $root_node_info->addAttribute($key, ' ');
697  else $root_node_info->addAttribute($key, $value);
698  }
699  $this->_getChildAssets($root_node_info, '1');
700  $assets_xml = $assets_node->asXML();
701 
702  // just get the root's XML not the tree's, because it is part of
703  // bigger things and we dont want the version info
704  header('Content-Type: text/xml');
705  ob_start();
706  echo "<initialisation>\n";
707  echo "<asset_types>\n";
708  $dir = SQ_DATA_PATH.'/private/asset_map';
709  if ($d = @opendir($dir)) {
710  while (($file = readdir($d)) !== FALSE) {
711  if (substr($file, -4) == '.xml') {
712  @readfile($dir.'/'.$file);
713  @ob_flush();
714  }
715  }
716  closedir($d);
717  }
718  echo "</asset_types>\n";
719  echo $current_user_xml;
720  echo $assets_xml;
721  echo "</initialisation>\n";
722  $out = ob_get_contents();
723  ob_end_clean();
724  echo $out;
725 
726  }//end _doInitialise()
727 
728 
738  function _convertCharset($string='', $charset='UTF-8')
739  {
740  // mb_ functions require mbstring extension
741  if (function_exists('mb_convert_encoding')) {
742  return mb_convert_encoding($string, $charset, SQ_CONF_DEFAULT_CHARACTER_SET);
743  } else {
744  return $string;
745  }
746 
747  }//end _convertCharset()
748 
749 
759  function _getAssetInfo($assetid, $linkid=0)
760  {
761 
762  $attrs = Array();
763  if (FALSE !== strpos($assetid, ':')) {
764  // This is a shadow asset so we need to get info differently
765  $bridge = $GLOBALS['SQ_SYSTEM']->am->getAsset(strtok($assetid, ':'));
766  $attrs = $bridge->getAssetMapAssetInfo($assetid);
767  if (empty($attrs)) {
768  // note that we pretend these assets have children so we dont have to actually
769  // load all their kids - we dont know what kind of speed hit we get for the different
770  // types of shadow assets
771  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
772 
773  if (!is_null($asset)) {
774  $attrs = Array(
775  'assetid' => $assetid,
776  'short_name' => $asset->short_name,
777  'name' => $asset->name,
778  'type_code' => $asset->type(),
779  'accessible' => 1,
780  'status' => $asset->status,
781  'url' => $asset->getURL(),
782  'web_path' => '',
783  'num_kids' => -1,
784  );
785  }
786  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
787  }
788  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($bridge);
789 
790  $attrs['assetid'] = urlencode($attrs['assetid']);
791 
792  } else {
793 
794  // Not a shadow asset
795  try {
796  $db = DAL::getDb();
797  $bind_vars = Array();
798 
799  $assetid = (String)$assetid;
800  $userid_cond = '';
801  if (!$GLOBALS['SQ_SYSTEM']->userRoot() && !$GLOBALS['SQ_SYSTEM']->userSystemAdmin()) {
802  $user =& $GLOBALS['SQ_SYSTEM']->am->getAsset($GLOBALS['SQ_SYSTEM']->currentUserId());
803  $userids = $user->getUserGroups();
804  $public_userid = (String)$GLOBALS['SQ_SYSTEM']->am->getSystemAssetid('public_user');
805  array_push($userids, $public_userid, (String)$GLOBALS['SQ_SYSTEM']->user->id);
806  $userid_cond = ' AND (p.userid IN (';
807  for (reset($userids); NULL !== ($k = key($userids)); next($userids)) {
808  $bind_vars['userid_' . $k] = $userids[$k];
809  $userid_cond .= ':userid_' . $k . ',';
810  }
811  $userid_cond = rtrim($userid_cond, ',') . ')';
812 
813  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
814  $userid_cond .= ' OR r.userid IN (';
815  for (reset($userids); NULL !== ($k = key($userids)); next($userids)) {
816  $bind_vars['role_userid_' . $k] = $userids[$k];
817  $userid_cond .= ':role_userid_' . $k . ',';
818  }
819  $userid_cond = rtrim($userid_cond, ',') . ')';
820  }
821  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($user);
822 
823  $userid_cond .= ') ';
824  }
825 
826  // work out what protocol we are using to get here so we can get the most
827  // relevent protocol for the preview urls
828  $primary_protocol = current_protocol();
829  if (empty($primary_protocol)) {
830  $primary_protocol = 'http';
831  }
832 
833  if ($primary_protocol == 'http') {
834  $secondary_protocol = 'https';
835  } else {
836  $secondary_protocol = 'http';
837  }
838 
839  $sql = 'SELECT l.assetid, l.short_name, l.name, l.type_code, l.status, u.url,
840  l.link_type, l.sort_order, ap.path,
841  (CASE u.'.$primary_protocol.'
842  WHEN \'1\' THEN :primary_protocol
843  WHEN \'0\' THEN :secondary_protocol
844  END) AS protocol';
845  $bind_vars['primary_protocol'] = $primary_protocol;
846  $bind_vars['secondary_protocol'] = $secondary_protocol;
847 
848  if (!empty($userid_cond)) {
849  $sql .= ', p.permission AS accessible';
850  } else {
851  $sql .= ', 1 AS accessible';
852  }
853 
854  $u_where = 'l.assetid = u.assetid';
855  $u_where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($u_where, 'u', 'ON');
856 
857  $ap_where = 'l.assetid = ap.assetid';
858  $ap_where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($ap_where, 'ap', 'ON');
859 
860  $sql .= ' FROM '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_lnk_minor l';
861  if (!empty($userid_cond)) {
862  $sql .= ' LEFT JOIN (SELECT p.assetid, p.permission
863  FROM '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_lnk_minor l2
864  INNER JOIN '.SQ_TABLE_RUNNING_PREFIX.'ast_perm p ON l2.assetid = p.assetid';
865 
866 
867  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
868  $sql .= ' LEFT JOIN '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_role r ON (p.userid = r.roleid AND r.assetid = l2.assetid)';
869  }
870 
871  $sql .= ' WHERE l2.assetid = :assetid_1 AND (';
872  $sql = $sql.'(
873  (p.permission = :p_permission AND (
874  p.userid <> :p_userid';
875 
876  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
877  $sql .= ' OR r.userid <> :r_userid';
878  }
879 
880  $sql .= ' OR (p.userid = :p_userid_1 AND p.granted = \'1\')';
881 
882  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
883  $sql .= ' OR (r.userid = :r_userid_1 AND p.granted = \'1\')';
884  }
885 
886  $sql .= ' )
887  )
888  OR (
889  p.permission > :p_permission_1 AND p.granted = \'1\'
890  )
891  ) '.$userid_cond.') GROUP BY p.assetid, p.permission HAVING MIN(p.granted) <> \'0\') p ON (l.assetid = p.assetid) ';
892 
893  $bind_vars['p_permission'] = SQ_PERMISSION_READ;
894  $bind_vars['p_permission_1'] = SQ_PERMISSION_READ;
895  $bind_vars['p_userid'] = $public_userid;
896  $bind_vars['p_userid_1'] = $public_userid;
897 
898  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
899  $bind_vars['r_userid'] = $public_userid;
900  $bind_vars['r_userid_1'] = $public_userid;
901  }
902 
903  $bind_vars['assetid_1'] = $assetid;
904  }
905 
906  $sql .= ' LEFT JOIN '.SQ_TABLE_RUNNING_PREFIX.'ast_url u '.$u_where.' ';
907  $sql .= ' LEFT JOIN '.SQ_TABLE_RUNNING_PREFIX.'ast_path ap '.$ap_where.' ';
908 
909  $where = ' l.assetid = :assetid_2';
910  $bind_vars['assetid_2'] = $assetid;
911 
912  if ($linkid && is_numeric($linkid)) {
913  $where .= ' AND l.linkid = :linkid';
914  $bind_vars['linkid'] = $linkid;
915  }
916 
917  $where .=' AND l.link_type <= :max_link_type';
918  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where, 'ast_', 'WHERE', FALSE);
919  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where, 'lnk_', 'WHERE', FALSE);
920 
921  $bind_vars['max_link_type'] = SQ_LINK_TYPE_2;
922 
923  $sql .= ' '.$where;
924  $query = MatrixDAL::preparePdoQuery($sql);
925  foreach ($bind_vars as $key => $value) {
926  MatrixDAL::bindValueToPdo($query, $key, $value);
927  }
928 
929  $assets = MatrixDAL::executePdoAssoc($query);
930  $asset = (!empty($assets)) ? $assets[0] : Array();
931 
932  } catch (Exception $e) {
933  throw new Exception('Failed to get Asset Info due to database error: '.$e->getMessage());
934  }
935  // if the asset map did a request for an asset that no longer exists
936  // then return nothing
937  if (empty($asset)) return Array();
938 
939  if (!isset($asset['accessible'])) {
940  $asset['accessible'] = 0;
941  }
942  if (empty($asset['accessible']) || $asset['accessible'] < 1) {
943  $asset['accessible'] = 0;
944  }
945  if ($asset['accessible'] > 1) {
946  $asset['accessible'] = 1;
947  }
948 
949  if (!empty($asset['url'])) {
950  $asset['url'] = $asset['protocol'].'://'.$asset['url'];
951  }
952 
953  $GLOBALS['SQ_SYSTEM']->am->includeAsset($asset['type_code']);
954  if (implements_interface($asset['type_code'], 'bridge')) {
955  $num_kids = -1;
956  } else {
957  try {
958  $bind_vars = Array();
959  $sql = 'SELECT COUNT(*)
960  FROM '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_lnk_major';
961  $where = 'majorid = :assetid AND link_type <= :max_link_type';
962  $bind_vars['assetid'] = $assetid;
963  $bind_vars['max_link_type'] = SQ_LINK_TYPE_2;
964  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where, 'ast_', 'WHERE', FALSE);
965  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where, 'lnk_', 'WHERE', FALSE);
966 
967  $query = MatrixDAL::preparePdoQuery($sql.' '.$where);
968  foreach ($bind_vars as $key => $value) {
969  MatrixDAL::bindValueToPdo($query, $key, $value);
970  }
971  $results = MatrixDAL::executePdoOne($query);
972  $num_kids = (!empty($results)) ? $results : 0;
973 
974  } catch (Exception $e) {
975  throw new Exception('Failed to get kids number due to database error: '.$e->getMessage());
976  }
977  }
978 
979  $attrs = Array(
980  'assetid' => urlencode($asset['assetid']),
981  'short_name' => $asset['short_name'],
982  'name' => $asset['name'],
983  'type_code' => $asset['type_code'],
984  'link_type' => $asset['link_type'],
985  'accessible' => $asset['accessible'],
986  'status' => $asset['status'],
987  'sort_order' => $asset['sort_order'],
988  'url' => $asset['url'],
989  'web_path' => $asset['path'],
990  'num_kids' => $num_kids,
991  'linkid' => urlencode($linkid),
992  );
993 
994  }//end else shadow asset
995 
996  // replace 'name' with the configured display name
997  $attrs['name'] = urlencode($this->_convertCharset($this->_getAssetDisplayName($attrs)));
998  if (isset($attrs['short_name'])) {
999  $attrs['short_name'] = urlencode($this->_convertCharset($attrs['short_name']));
1000  }
1001 
1002  return $attrs;
1003 
1004  }//end _getAssetInfo()
1005 
1006 
1019  function _getChildAssets(&$root, $assetid, $dependants_only=FALSE, $start=0, $limit=0)
1020  {
1021  // make sure permission is checked for parent asset. asset map doesn't need status check, just assume it's always live
1022  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
1023  if($asset) {
1024  $status = $asset->status;
1025  $asset->status = SQ_STATUS_LIVE;
1026  if(!($asset->readAccess())) {
1027  $this->_error('AMAP0047', $asset->name, $asset->id);
1028  exit();
1029  }
1030  $asset->status = $status;
1031  }
1032 
1033  $db_result = Array();
1034  $num_kids = NULL;
1035  try {
1036  $db = MatrixDAL::getDb();
1037  $assetid = (String)$assetid;
1038  $userid_cond = '';
1039  $bind_vars = array();
1040  if (!$GLOBALS['SQ_SYSTEM']->userRoot() && !$GLOBALS['SQ_SYSTEM']->userSystemAdmin()) {
1041  $user =& $GLOBALS['SQ_SYSTEM']->am->getAsset($GLOBALS['SQ_SYSTEM']->currentUserId());
1042  $userids = $user->getUserGroups();
1043  $public_userid = (String)$GLOBALS['SQ_SYSTEM']->am->getSystemAssetid('public_user');
1044 
1045  array_push($userids, $public_userid, (String)$GLOBALS['SQ_SYSTEM']->user->id);
1046  $userid_cond = ' AND (p.userid IN (';
1047  for (reset($userids); NULL !== ($k = key($userids)); next($userids)) {
1048  $bind_vars['userid_' . $k] = $userids[$k];
1049  $userid_cond .= ':userid_' . $k . ',';
1050  }
1051  $userid_cond = rtrim($userid_cond, ',') . ')';
1052 
1053  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
1054  $userid_cond .= ' OR r.userid IN (';
1055  for (reset($userids); NULL !== ($k = key($userids)); next($userids)) {
1056  $bind_vars['role_userid_' . $k] = $userids[$k];
1057  $userid_cond .= ':role_userid_' . $k . ',';
1058  }
1059  $userid_cond = rtrim($userid_cond, ',') . ')';
1060  }
1061  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($user);
1062 
1063  $userid_cond .= ') ';
1064  }
1065 
1066  // work out what protocol we are using to get here so we can get the most
1067  // relevent protocol for the preview urls
1068  $primary_protocol = current_protocol();
1069  if (empty($primary_protocol)) {
1070  $primary_protocol = 'http';
1071  }
1072 
1073  if ($primary_protocol == 'http') {
1074  $secondary_protocol = 'https';
1075  } else {
1076  $secondary_protocol = 'http';
1077  }
1078 
1079  $sql = 'SELECT l.assetid, l.short_name, l.name, l.type_code, l.status,
1080  l.linkid, l.link_type, l.sort_order, l.is_dependant, ap.path, u.url,
1081  (CASE u.'.$primary_protocol.'
1082  WHEN \'1\' THEN :primary_protocol
1083  WHEN \'0\' THEN :secondary_protocol
1084  END) AS protocol';
1085  $bind_vars['primary_protocol'] = $primary_protocol;
1086  $bind_vars['secondary_protocol'] = $secondary_protocol;
1087 
1088  if (!empty($userid_cond)) {
1089  $sql .= ', p.permission AS accessible';
1090  } else {
1091  $sql .= ', 1 AS accessible';
1092  }
1093 
1094  $sql .= ' FROM '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_lnk_minor l';
1095 
1096  if (!empty($userid_cond)) {
1097  $sql .= ' LEFT JOIN (SELECT p.assetid, p.permission
1098  FROM '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_lnk_minor l2
1099  INNER JOIN '.SQ_TABLE_RUNNING_PREFIX.'ast_perm p ON l2.assetid = p.assetid';
1100 
1101  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
1102  $sql .= ' LEFT JOIN '.SQ_TABLE_RUNNING_PREFIX.'vw_ast_role r ON (p.userid = r.roleid AND r.assetid = l2.assetid)';
1103  }
1104 
1105  $sql .= ' WHERE l2.majorid = :assetid_1 AND (';
1106  $sql = $sql.'(
1107  (p.permission = :p_permission AND (
1108  p.userid <> :p_userid';
1109 
1110  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
1111  $sql .= ' OR r.userid <> :r_userid';
1112  }
1113 
1114  $sql .= ' OR (p.userid = :p_userid_1 AND p.granted = \'1\')';
1115 
1116  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
1117  $sql .= ' OR (r.userid = :r_userid_1 AND p.granted = \'1\')';
1118  }
1119 
1120  $sql .='
1121  )
1122  )
1123  OR (
1124  p.permission > :p_permission_1 AND p.granted = \'1\'
1125  )
1126  ) '.$userid_cond.') GROUP BY p.assetid, p.permission HAVING MIN(p.granted) <> \'0\') p ON (l.assetid = p.assetid) ';
1127 
1128  $bind_vars['p_permission'] = SQ_PERMISSION_READ;
1129  $bind_vars['p_permission_1'] = SQ_PERMISSION_READ;
1130  $bind_vars['p_userid'] = $public_userid;
1131  $bind_vars['p_userid_1'] = $public_userid;
1132 
1133  if (SQ_CONF_ENABLE_ROLES_PERM_SYSTEM == '1') {
1134  $bind_vars['r_userid'] = $public_userid;
1135  $bind_vars['r_userid_1'] = $public_userid;
1136  }
1137 
1138  $bind_vars['assetid_1'] = $assetid;
1139  }
1140 
1141  $u_where = 'l.assetid = u.assetid';
1142  $u_where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($u_where, 'u', 'ON');
1143  $sql .= ' LEFT JOIN '.SQ_TABLE_RUNNING_PREFIX.'ast_url u '.$u_where;
1144 
1145  $ap_where = 'l.assetid = ap.assetid';
1146  $ap_where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($ap_where, 'ap', 'ON');
1147  $sql .= ' LEFT JOIN '.SQ_TABLE_RUNNING_PREFIX.'ast_path ap '.$ap_where;
1148 
1149  $where = 'l.majorid = :assetid_2';
1150  $bind_vars['assetid_2'] = $assetid;
1151 
1152  if ($dependants_only) {
1153  $where .= ' AND l.is_dependant = :is_dependant';
1154  $bind_vars['is_dependant'] = '1';
1155  }
1156  $where .= ' AND
1157  l.link_type <= :max_link_type';
1158  $bind_vars['max_link_type'] = SQ_LINK_TYPE_2;
1159 
1160  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where, 'ast_', 'WHERE', FALSE);
1161  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where, 'lnk_', 'WHERE', FALSE);
1162 
1163  $sql .= ' '.$where;
1164  $sql .= ' ORDER BY sort_order';
1165 
1166  $query = MatrixDAL::preparePdoQuery($sql);
1167  foreach($bind_vars as $key => $value) {
1168  MatrixDAL::bindValueToPdo($query, $key, $value);
1169  }
1170  $db_result = MatrixDAL::executePdoAssoc($query);
1171 
1172  } catch (Exception $e) {
1173  throw new Exception('Unable to get all the children due to database error: '.$e->getMessage());
1174  }
1175 
1176  // create the result array to be a single (assetid => asset_data)
1177  // because the DB result contains multiple entries because of possible multiple URLs
1178  $result = Array();
1179  $skipped = Array();
1180  $res_count = 0;
1181  $added = 0;
1182  foreach ($db_result as $db_result_v) {
1183  if (isset($skipped[$db_result_v['assetid']]) === true) continue;
1184  if ($res_count >= $start) {
1185  if (isset($result[$db_result_v['assetid']]) === true) continue;
1186  $result[$db_result_v['assetid']] = $db_result_v;
1187  if (($limit > 0) && ($added >= $limit-1)) {
1188  break;
1189  }
1190  $added++;
1191  } else {
1192  $skipped[$db_result_v['assetid']] = 1;
1193  $res_count++;
1194  }
1195  }
1196  unset($db_result);
1197  unset($bind_vars);
1198  try {
1199  $bind_vars = Array();
1200  // Search both tables (sq_ast_lnk - 1 and sq_shdw_ast_lnk - 2) and union the results
1201  $sql1 = 'SELECT majorid, COUNT(*) as link_count FROM '.SQ_TABLE_RUNNING_PREFIX.'ast_lnk';
1202  $sql2 = 'SELECT majorid, COUNT(*) as link_count FROM '.SQ_TABLE_RUNNING_PREFIX.'shdw_ast_lnk';
1203 
1204  $sub_sql1 = 'SELECT minorid FROM '.SQ_TABLE_RUNNING_PREFIX.'ast_lnk';
1205  $sub_sql2 = 'SELECT minorid FROM '.SQ_TABLE_RUNNING_PREFIX.'shdw_ast_lnk';
1206  $sub_where1 = 'majorid = :assetid';
1207  $sub_where2 = 'majorid = :assetid2';
1208  $bind_vars['assetid'] = $assetid;
1209  $bind_vars['assetid2'] = $assetid;
1210  $sub_where1 = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($sub_where1, NULL, 'WHERE', FALSE);
1211  $sub_where1 = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($sub_where1, NULL, 'WHERE', FALSE);
1212  $sub_where2 = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($sub_where2, NULL, 'WHERE', FALSE);
1213  $sub_where2 = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($sub_where2, NULL, 'WHERE', FALSE);
1214  $sub_sql = $sub_sql1.' '.$sub_where1.' GROUP BY minorid UNION ALL '.$sub_sql2.' '.$sub_where2.' GROUP BY minorid';
1215 
1216  $where_clause = 'majorid IN ('.$sub_sql.') AND link_type <= :max_link_type';
1217  $bind_vars['max_link_type'] = SQ_LINK_TYPE_2;
1218 
1219  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where_clause, NULL, 'WHERE', FALSE);
1220  $where = $GLOBALS['SQ_SYSTEM']->constructRollbackWhereClause($where_clause, NULL, 'WHERE', FALSE);
1221  $where .= ' GROUP BY majorid ';
1222 
1223  $query2 = MatrixDAL::preparePdoQuery($sql1.' '.$where.' UNION ALL '.$sql2.' '.$where);
1224  foreach ($bind_vars as $key => $value) {
1225  MatrixDAL::bindValueToPdo($query2, $key, $value);
1226  }
1227  $db_result = MatrixDAL::executePdoAssoc($query2);
1228  if (!empty($db_result))
1229  {
1230  foreach ($db_result as $key => $value) {
1231  if (isset($num_kids[$value['majorid']])) {
1232  $num_kids[$value['majorid']] = $num_kids[$value['majorid']] + $value['link_count'];
1233  } else {
1234  $num_kids[$value['majorid']] = $value['link_count'];
1235  }//end if
1236  }
1237  }
1238  } catch (Exception $e) {
1239  throw new Exception('Failed to get the number of children due to database error: '.$e->getMessage());
1240  }
1241 
1242  // gather links for shadowed assets - only if asset descends from a bridge
1243  $asset_info = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo(Array($assetid));
1244  $implements_shadow_assets = FALSE;
1245 
1246  if (strpos($assetid, ':') !== FALSE) {
1247  // this is a shadow asset itself, so it will work the same way as a bridge
1248  $implements_shadow_assets = TRUE;
1249  } else if (isset($asset_info[$assetid]['type_code']) && !empty($asset_info[$assetid]['type_code'])) {
1250  $type_code = $asset_info[$assetid]['type_code'];
1251 
1252  $GLOBALS['SQ_SYSTEM']->am->includeAsset($type_code);
1253  $implements_shadow_assets = implements_interface($type_code, 'bridge');
1254  }
1255 
1256  if ($implements_shadow_assets) {
1257  $links_handler = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
1258 
1259  if (!is_null($links_handler)) {
1260  // it may be able to handle this itself, lets check
1261  if (method_exists($links_handler, 'getAssetMapLinks')) {
1262  $result = array_merge($result, $links_handler->getAssetMapLinks());
1263  if ($limit !=0) {
1264  $chunk = Array();
1265  for ($i = $start; $i < $start+$limit; $i++) {
1266  if (!isset($result[$i])) break;
1267  $chunk[$i - $start] = $result[$i];
1268  }
1269  $result = $chunk;
1270  $chunk = NULL;
1271  }
1272 
1273  } else {
1274  $links = $GLOBALS['SQ_SYSTEM']->am->getLinks($assetid, SQ_LINK_TYPE_1 | SQ_LINK_TYPE_2);
1275  $skipped = 0;
1276  $added = 0;
1277 
1278  foreach ($links as $link_data) {
1279 
1280  // if the colon isn't there, this isn't a shadow asset - move on
1281  if (strpos($link_data['minorid'], ':') === FALSE) {
1282  continue;
1283  }
1284 
1285  if ($limit !=0) {
1286  if ($start > $skipped) {
1287  $skipped++;
1288  continue;
1289  }
1290 
1291  if ($limit == $added) break;
1292  $added++;
1293  }
1294 
1295  // note that we pretend these assets have children so we dont have to actually
1296  // load all their kids - we dont know what kind of speed hit we get for the different
1297  // types of shadow assets
1298  $link_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($link_data['minorid'], $link_data['minor_type_code']);
1299 
1300  $result[] = Array(
1301  'assetid' => $link_data['minorid'],
1302  'name' => $link_asset->name,
1303  'short_name' => $link_asset->short_name,
1304  'accessible' => 1,
1305  'type_code' => $link_data['minor_type_code'],
1306  'status' => $link_asset->status,
1307  'linkid' => $link_data['majorid'].':'.$link_data['minorid'],
1308  'link_type' => $link_data['link_type'],
1309  'num_kids' => -1,
1310  'sort_order' => $link_data['sort_order'],
1311  'url' => $link_asset->getURL(),
1312  'path' => '',
1313  'is_dependant' => $link_data['is_dependant']
1314  );
1315  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($link_asset);
1316  }//end foreach
1317  }//end else
1318  }//end if
1319  }//end if is a bridge
1320  foreach ($result as $asset) {
1321  if (!isset($asset['num_kids'])) {
1322  $default_kids = 0;
1323  if (isset($asset['type_code']) && !empty($asset['type_code'])) {
1324  $type_code = $asset['type_code'];
1325  $GLOBALS['SQ_SYSTEM']->am->includeAsset($type_code);
1326  if (implements_interface($type_code, 'bridge')) {
1327  $num_kids[$asset['assetid']] = -1;
1328  }
1329  }
1330  $asset['num_kids'] = array_get_index($num_kids, $asset['assetid'], $default_kids);
1331  }
1332 
1333  if (!isset($asset['accessible'])) {
1334  $asset['accessible'] = 0;
1335  }
1336  if (empty($asset['accessible']) || $asset['accessible'] < 1) {
1337  $asset['accessible'] = 0;
1338  }
1339  if ($asset['accessible'] > 1) {
1340  $asset['accessible'] = 1;
1341  }
1342 
1343  if (!empty($asset['url']) && isset($asset['protocol'])) {
1344  $asset['url'] = $asset['protocol'].'://'.$asset['url'];
1345  }
1346 
1347  // if the child is a shadow asset, but the parent is not a bridge
1348  // then its a shadow asset linked underneath a real asset, so we
1349  // will need some information about the asset
1350  $id_parts = explode(':', $asset['assetid']);
1351  if (isset($id_parts[1]) && !$implements_shadow_assets) {
1352  $bridge = $GLOBALS['SQ_SYSTEM']->am->getAsset($id_parts[0]);
1353  $shdw_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($asset['assetid']);
1354 
1355  // We dont want asset map to break so make sure we send valid values
1356  if ($shdw_asset != NULL) {
1357  $asset['short_name'] = $shdw_asset->short_name;
1358  $asset['type_code'] = $shdw_asset->type();
1359  } else {
1360  $asset['short_name'] = translate('asset_not_found', $asset['assetid']);
1361  $asset['type_code'] = '';
1362  }
1363  $asset['status'] = $bridge->status;
1364  $asset['num_kids'] = -1;
1365  $asset['accessible'] = $bridge->readAccess();
1366  }
1367 
1368  $attrs = Array(
1369  'assetid' => urlencode($asset['assetid']),
1370  'type_code' => $asset['type_code'],
1371  'link_type' => $asset['link_type'],
1372  'accessible' => $asset['accessible'],
1373  'status' => $asset['status'],
1374  'linkid' => urlencode($asset['linkid']),
1375  'num_kids' => $asset['num_kids'],
1376  'sort_order' => $asset['sort_order'],
1377  'url' => urlencode($asset['url']),
1378  'web_path' => urlencode($asset['path']),
1379  'is_dependant' => $asset['is_dependant'],
1380  );
1381 
1382  $attrs['name'] = urlencode($this->_convertCharset($this->_getAssetDisplayName($asset)));
1383  if (!$attrs['accessible']) $attrs['child_count'] = 0;
1384 
1385  $tmp_node = $root->addChild('asset');
1386  foreach ($attrs as $key => $value) {
1387  if (strlen($value) == 0) $tmp_node->addAttribute($key, ' ');
1388  else $tmp_node->addAttribute($key, $value);
1389  }
1390  }//end foreach
1391 
1392  }//end _getChildAssets()
1393 
1394 
1403  function _getAssetDisplayName($asset)
1404  {
1405  // get the string from the config var and replace the assetid, name and shortname
1406  $display_name = SQ_CONF_ASSET_MAP_ASSET_DISPLAY_NAME;
1407  if (!isset($this->_tmp['display_name_keywords'])) {
1408  $keywords = Array (
1409  'assetid',
1410  'name',
1411  'short_name',
1412  'type_code',
1413  'status',
1414  'num_kids',
1415  );
1416  foreach ($keywords as $keyword) {
1417  if (FALSE !== strpos(SQ_CONF_ASSET_MAP_ASSET_DISPLAY_NAME, '%asset_'.$keyword.'%')) {
1418  $this->_tmp['display_name_keywords'][] = $keyword;
1419  }
1420  }
1421  }
1422 
1423  foreach ($this->_tmp['display_name_keywords'] as $keyword) {
1424  $replacement_value = array_get_index($asset, $keyword);
1425  switch ($keyword) {
1426  case 'assetid':
1427  $replacement_value = urldecode(array_get_index($asset, $keyword));
1428  break;
1429  case 'type_code':
1430  $replacement_value = $GLOBALS['SQ_SYSTEM']->am->getTypeInfo($replacement_value, 'name');
1431  break;
1432  case 'status':
1433  $status_names = get_status_names();
1434  $replacement_value = $status_names[$replacement_value];
1435  break;
1436  case 'num_kids':
1437  if ($replacement_value=='-1') {
1438  $replacement_value = 'N/A';
1439  }
1440  break;
1441  }
1442  $display_name = str_replace('%asset_'.$keyword.'%', $replacement_value, $display_name);
1443  }
1444 
1445  return $display_name;
1446 
1447  }//end _getAssetDisplayName()
1448 
1449 
1458  function _getAssets(&$input)
1459  {
1460 
1461  $output = simplexml_load_string('<xml></xml>');
1462  $root = $output->addChild('assets');
1463  //$output = new XML_Tree();
1464  //$root = $output->addRoot('assets', '');
1465  $done = Array();
1466 
1467  // go through the kids and add them to the $root
1468  foreach ($input->children() as $k => $v) {
1469 
1470  // get all the attribute values
1471  $tmp_info = Array();
1472  foreach ($v->attributes() as $a => $b) {
1473  $tmp_info[$a] = urldecode((string)$b);
1474  }
1475 
1476  if (empty($tmp_info['assetid'])) continue;
1477 
1478  if (array_key_exists(urldecode($tmp_info['assetid']), $done)) {
1479  // Double check
1480  $linkid_check = ($done[urldecode($tmp_info['assetid'])]['linkid'] == urldecode($tmp_info['linkid']));
1481  $start_check = ($done[urldecode($tmp_info['assetid'])]['start'] == urldecode($tmp_info['start']));
1482  $limit_check = ($done[urldecode($tmp_info['assetid'])]['limit'] == urldecode($tmp_info['limit']));
1483  if ($linkid_check && $start_check && $limit_check) {
1484  continue;
1485  }
1486  }//end if
1487 
1488  // get the information about the asset
1489  $info = $this->_getAssetInfo(urldecode($tmp_info['assetid']), urldecode($tmp_info['linkid']));
1490 
1491  // Place in done array, so we don't double up
1492  $done[urldecode($tmp_info['assetid'])] = Array(
1493  'linkid' => urldecode($tmp_info['linkid']),
1494  'start' => urldecode($tmp_info['start']),
1495  'limit' => urldecode($tmp_info['limit']),
1496  );
1497 
1498  // create a new node and fill out the attributes
1499  $tmp_node = $root->addChild('asset');
1500  foreach ($info as $info_k => $info_v) {
1501  if (strlen($info_v) == 0) $tmp_node->addAttribute($info_k, ' ');
1502  else $tmp_node->addAttribute($info_k, $info_v);
1503  }
1504 
1505  // add the children to the newly created node
1506  $this->_getChildAssets($tmp_node, $tmp_info['assetid'], FALSE, $tmp_info['start'], $tmp_info['limit']);
1507  }
1508 
1509  $this->_send($root);
1510 
1511  }//end _getAssets()
1512 
1513 
1523  function _getURL(&$input, &$backend)
1524  {
1525  /* input sample
1526  <?xml version="1.0"?>
1527  <command action="get url" cmd="add" parent_assetid="1" pos="5" type_code="folder"/>
1528  */
1529 
1530  $response_count = 0;
1531 
1532  $link = '';
1533  $frame = '';
1534  $action_info = Array();
1535  foreach ($input->attributes() as $k => $v) {
1536  $action_info[$k] = (string)$v;
1537  }
1538 
1539  switch ($action_info['cmd']) {
1540  case 'add' :
1541 
1542  $parent_assetid = urldecode($action_info['parent_assetid']);
1543  if (empty($parent_assetid) || !isset($action_info['pos']) || empty($action_info['type_code'])) {
1544  $this->_error('AMAP0007');
1545  return;
1546  }
1547 
1548  $parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($parent_assetid, '', TRUE);
1549  if (is_null($parent)) {
1550  $this->_error('AMAP0008', $parent_assetid);
1551  return;
1552  }
1553 
1554  if ($GLOBALS['SQ_SYSTEM']->am->assetInTrash($parent_assetid, TRUE)) {
1555  $this->_error('AMAP0009', $attr['parent_assetid']);
1556  return;
1557  }
1558 
1559  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
1560  if ($trash_folder->id == $parent_assetid) {
1561  $this->_error('AMAP0010');
1562  return;
1563  }
1564 
1565  $use_link_type = 0;
1566  $error_message = '';
1567  $link_types = Array(SQ_LINK_TYPE_1, SQ_LINK_TYPE_2);
1568  foreach ($link_types as $link_type) {
1569  if (TRUE === ($error_message = $GLOBALS['SQ_SYSTEM']->am->canLinkToType($parent, $action_info['type_code'], $link_type))) {
1570  // use this type
1571  $use_link_type = $link_type;
1572  break;
1573  }
1574  }
1575 
1576  if (!$use_link_type) {
1577  $this->_error('AMAP0011', $error_message);
1578  return;
1579  }
1580 
1581  // check for plain write access, don't check for lock because locking happens in Asset::create()
1582  if (!$parent->writeAccess('')) {
1583  $this->_error('AMAP0012');
1584  return;
1585  }
1586 
1587  // if we get this far then it's all good
1588  $link = current_url().'?SQ_BACKEND_PAGE=main'
1589  .'&backend_section=am'
1590  .'&am_section=add_asset'
1591  .'&type_code='.urlencode($action_info['type_code'])
1592  .'&link_type='.urlencode($use_link_type)
1593  .'&parent_assetid='.$parent_assetid
1594  .'&pos='.urlencode($action_info['pos']);
1595 
1596  $frame = 'sq_main';
1597 
1598  break;
1599 
1600  default :
1601  $this->_error('AMAP0013', $input->root->attributes['name']);
1602  return;
1603 
1604  }//end switch
1605  if (empty($link) || empty($frame)) {
1606  $this->_error('AMAP0014');
1607  return;
1608  }
1609 
1610  /* we want to return the following xml
1611  <?xml version="1.0"?>
1612  <responses>
1613  <url frame="sq_main">http://delta.squiz.net/colivar_dev/_admin/?SQ_BACKEND_PAGE=main&amp;backend_section=am&amp;am_section=add_asset&amp;type_code=folder&amp;link_type=1&amp;parent_assetid=1&amp;pos=5</url>
1614  </responses>
1615  */
1616 
1617  $output = simplexml_load_string('<xml></xml>');
1618  $responses = $output->addChild('responses');
1619  $url_tree = $responses->addChild('url', htmlentities($link, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
1620  $url_tree->addAttribute('frame', $frame);
1621 
1622  $this->_send($responses);
1623 
1624  }//end _getURL()
1625 
1626 
1636  function _moveAsset(&$input, &$backend)
1637  {
1638  $output = new XML_Tree();
1639  $output->addRoot('responses');
1640  $response_count = 0;
1641 
1642  // ensure no url friendly values exists for assetids
1643  $input->root->attributes['to_parent_assetid'] = urldecode($input->root->attributes['to_parent_assetid']);
1644  $input->root->attributes['from_parent_assetid'] = urldecode($input->root->attributes['from_parent_assetid']);
1645  foreach ($input->root->children as $index =>$child) {
1646  $input->root->children[$index]->attributes['assetid'] = urldecode($child->attributes['assetid']);
1647  }
1648 
1649  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($input->root->attributes['from_parent_assetid']);
1650  if (is_null($old_parent)) {
1651  $this->_error('AMAP0015', $input->root->attributes['from_parent_assetid']);
1652  return;
1653  }
1654 
1655  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById($input->root->attributes['linkid'], $old_parent->id);
1656 
1657  if (empty($link)) {
1658  $this->_error('AMAP0016', $input->root->attributes['linkid']);
1659  return;
1660  }
1661 
1662  $linkid = NULL;
1663 
1664  // if the from and to parentids are the same we are realy just altering the sort order for a parent
1665  if ($old_parent->id == $input->root->attributes['to_parent_assetid']) {
1666 
1667  // Let's just move the link
1668  if (!$GLOBALS['SQ_SYSTEM']->am->moveLinkPos($link['linkid'], $input->root->attributes['to_parent_pos'])) {
1669  return;
1670  }
1671 
1672  $linkid = $link['linkid'];
1673 
1674  $successTree = new XML_Tree();
1675  $successTree->addRoot('success', '', Array('linkid' => $linkid));
1676  $output->insertChild(Array('responses'), $response_count++, $successTree);
1677 
1678  } else {
1679  if ($link['locked'] == '1') {
1680  $this->_error('AMAP0046', $link['minorid']);
1681  return;
1682  }
1683 
1684  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['minorid'], $link['minor_type_code']);
1685  if (is_null($asset)) {
1686  $this->_error('AMAP0017', $link['minorid']);
1687  return;
1688  }
1689 
1690  // check if we are allowed to delete this link
1691  if (($err_msg = $old_parent->isDeletableLink($link['linkid'])) !== TRUE) {
1692  $this->_error('AMAP0018', $err_msg);
1693  return;
1694  }
1695 
1696  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($input->root->attributes['to_parent_assetid']);
1697  if (is_null($new_parent)) {
1698  $this->_error('AMAP0019', $input->root->attributes['to_parent_assetid']);
1699  return;
1700  }
1701 
1702  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1703  $vars = Array(
1704  'linkid' => $link['linkid'],
1705  'parentid' => $new_parent->id,
1706  'old_parentid' => $old_parent->id,
1707  'link_type' => $link['link_type'],
1708  'to_parent_pos' => $input->root->attributes['to_parent_pos'],
1709  );
1710 
1711  $hh->queueHipo('hipo_job_create_link', $vars);
1712 
1713  // check for any HIPOs that have been queued
1714  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1715  $url = $hh->runQueuedJobs('Javascript: function closeWindow() { setTimeout(\'window.close()\', 500); } closeWindow();');
1716 
1717  if (!empty($url)) {
1718  $urlTree = new XML_Tree();
1719  $urlTree->addRoot('url', $url, Array('js_function' => 'asset_map_popup'));
1720  $output->insertChild(Array('responses'), $response_count++, $urlTree);
1721  }
1722 
1723  }//end else
1724 
1725 
1726  $this->_send($output);
1727 
1728  }//end _moveAsset()
1729 
1730 
1740  function _cloneAsset(&$input, &$backend)
1741  {
1742  $output = new XML_Tree();
1743  $output->addRoot('responses');
1744  $response_count = 0;
1745 
1746  // ensure no url friendly values exists for assetids
1747  $input->root->attributes['to_parent_assetid'] = urldecode($input->root->attributes['to_parent_assetid']);
1748  $input->root->attributes['from_parent_assetid'] = urldecode($input->root->attributes['from_parent_assetid']);
1749  foreach ($input->root->children as $index =>$child) {
1750  $input->root->children[$index]->attributes['assetid'] = urldecode($child->attributes['assetid']);
1751  }
1752 
1753  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($input->root->attributes['from_parent_assetid']);
1754  if (is_null($old_parent)) {
1755  $this->_error('AMAP0020', $input->root->attributes['from_parent_assetid']);
1756  return;
1757  }
1758 
1759  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById($input->root->attributes['linkid'], $old_parent->id);
1760  if (empty($link)) {
1761  $this->_error('AMAP0021', $input->root->attributes['linkid']);
1762  return;
1763  }
1764 
1765  $linkid = NULL;
1766 
1767  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['minorid'], $link['minor_type_code']);
1768  if (is_null($asset)) {
1769  $this->_error('AMAP0022', $link['minorid']);
1770  return;
1771  }
1772 
1773  // check to see if the root asset chosen can be cloned
1774  if (!$asset->canClone()) {
1775  $this->_error('AMAP0023', $asset->name, (ucwords(str_replace('_', ' ', $asset->type()))));
1776  }
1777 
1778  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($input->root->attributes['to_parent_assetid']);
1779  if (is_null($new_parent)) {
1780  $this->_error('AMAP0024', $input->root->attributes['to_parent_assetid']);
1781  return;
1782  }
1783 
1784  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1785  $vars = Array(
1786  'assetid' => $asset->id,
1787  'type_code' => $asset->type(),
1788  'to_parent_assetid' => $new_parent->id,
1789  'to_parent_pos' => $input->root->attributes['to_parent_pos'],
1790  );
1791  $hh->queueHipo('hipo_job_clone_asset', $vars);
1792 
1793  // check for any HIPOs that have been queued
1794  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1795  $url = $hh->runQueuedJobs('Javascript: function closeWindow() { setTimeout(\'window.close()\', 500); } closeWindow();');
1796 
1797  if (!empty($url)) {
1798  $urlTree = new XML_Tree();
1799  $urlTree->addRoot('url', $url, Array('js_function' => 'asset_map_popup'));
1800  $output->insertChild(Array('responses'), $response_count++, $urlTree);
1801  }
1802 
1803  $this->_send($output);
1804 
1805  }//end _cloneAsset()
1806 
1807 
1816  function _newLink(&$input)
1817  {
1818  $output = new XML_Tree();
1819  $root = $output->addRoot('responses');
1820  $response_count = 0;
1821 
1822  // ensure no url friendly values exists for assetids
1823  $input->root->attributes['to_parent_assetid'] = urldecode($input->root->attributes['to_parent_assetid']);
1824  $input->root->attributes['from_parent_assetid'] = urldecode($input->root->attributes['from_parent_assetid']);
1825  foreach ($input->root->children as $index =>$child) {
1826  $input->root->children[$index]->attributes['assetid'] = urldecode($child->attributes['assetid']);
1827  }
1828 
1829  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($input->root->attributes['from_parent_assetid']);
1830  if (is_null($old_parent)) {
1831  $this->_error('AMAP0025', $input->root->attributes['from_parent_assetid']);
1832  return;
1833  }
1834 
1835  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById($input->root->attributes['linkid'], $old_parent->id);
1836  if (empty($link)) {
1837  $this->_error('AMAP0026', $input->root->attributes['linkid']);
1838  return;
1839  }
1840 
1841  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['minorid'], $link['minor_type_code']);
1842  if (is_null($asset)) {
1843  $this->_error('AMAP0027', $link['minorid']);
1844  return;
1845  }
1846 
1847  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($input->root->attributes['to_parent_assetid']);
1848  if (is_null($new_parent)) {
1849  $this->_error('AMAP0028', $input->root->attributes['to_parent_assetid']);
1850  return;
1851  }
1852 
1853  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
1854  if ($trash_folder->id == $input->root->attributes['to_parent_assetid']) {
1855  $this->_error('AMAP0029');
1856  return;
1857  }
1858 
1859  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1860  $vars = Array(
1861  'assetid' => $asset->id,
1862  'parentid' => $new_parent->id,
1863  'link_type' => $link['link_type'],
1864  'to_parent_pos' => $input->root->attributes['to_parent_pos'],
1865  );
1866  $hh->queueHipo('hipo_job_create_link', $vars);
1867 
1868  $url = $hh->runQueuedJobs('Javascript: function closeWindow() { setTimeout(\'window.close()\', 700); } closeWindow();');
1869 
1870  if (!empty($url)) {
1871  $urlTree = new XML_Tree();
1872  $urlTree->addRoot('url', $url, Array('js_function' => 'asset_map_popup'));
1873  $root = $output->insertChild('responses', $response_count++, $urlTree);
1874  }
1875 
1876  $this->_send($output);
1877 
1878  }//end _newLink()
1879 
1880 
1896  function _moveAssets($input)
1897  {
1898  /* EXAMPLE of input
1899  <?xml version="1.0"?>
1900  <command action="move asset" to_parent_assetid="10" to_parent_pos="0">
1901  <asset assetid="50" linkid="49" parentid="37"/>
1902  </command>
1903  */
1904 
1905  $output = simplexml_load_string('<xml></xml>');
1906  $responses = $output->addChild('responses');
1907 
1908  $response_count = 0;
1909 
1910  // Make sure urlencoded assetids are restored correctly in xml
1911  $input = $this->_fixUrlencodedAssetids($input);
1912 
1913  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$input->attributes()->to_parent_assetid);
1914  $new_parent_pos = (string)$input->attributes()->to_parent_pos;
1915 
1916  if (is_null($new_parent)) {
1917  $this->_error('AMAP0030', (string)$input->attributes()->to_parent_assetid);
1918  return;
1919  }
1920 
1921  $assets = Array();
1922  $reordered_assets = Array();
1923 
1924  // get information about the assets to move
1925  foreach ($input->asset as $asset_node) {
1926  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$asset_node->attributes()->assetid);
1927  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset(urldecode((string)$asset_node->attributes()->parentid));
1928  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById((string)$asset_node->attributes()->linkid, $old_parent->id);
1929 
1930  if (is_null($old_parent)) {
1931  $this->_error('AMAP0031', $input->attributes()->from_parent_assetid);
1932  return;
1933  }
1934 
1935  if (empty($link)) {
1936  $this->_error('AMAP0032', $asset_node->attributes()->linkid);
1937  return;
1938  }
1939 
1940  if (($err_msg = $old_parent->isDeletableLink($link['linkid'])) !== TRUE) {
1941  $this->_error('AMAP0033', $err_msg);
1942  return;
1943  }
1944 
1945  if ($link['locked'] == '1') {
1946  $this->_error('AMAP0046', $link['minorid']);
1947  return;
1948  }
1949 
1950  if (is_null($asset)) {
1951  $this->_error('AMAP0034', $link['minorid']);
1952  return;
1953  }
1954 
1955  if ($old_parent->id == $new_parent->id) {
1956  $reordered_assets[$asset->id] = Array(
1957  'linkid' => $link['linkid'],
1958  'sort_order' => $link['sort_order'],
1959  'parentid' => $old_parent->id,
1960  );
1961  } else {
1962  // account for multiple links to the same asset being moved
1963  // it'll likely result in an error if we're moving to anywhere but the trash, however
1964  if (!isset($assets[$asset->id])) {
1965  $assets[$asset->id] = Array();
1966  }
1967  $assets[$asset->id][] = Array(
1968  'linkid' => $link['linkid'],
1969  'parentid' => $old_parent->id,
1970  );
1971  }
1972 
1973  }//end foreach
1974 
1975  // process the re-ordering
1976  foreach ($reordered_assets as $assetid => $link_info) {
1977 
1978  // Check write access as appropriate
1979  if ($GLOBALS['SQ_SYSTEM']->runLevelEnables(SQ_SECURITY_PERMISSIONS)) {
1980  $majwa = $old_parent->writeAccess('');
1981  $minwa = $asset->writeAccess('');
1982  if (!($majwa || $minwa)) {
1983  $reordering_errors = translate('cannot_reorder_sig_link_no_perm_either', $asset->name, $asset->id, $old_parent->name, $old_parent->id);
1984  $this->_error('AMAP0045', $reordering_errors);
1985  } else if (!$majwa) {
1986  $reordering_errors = translate('cannot_reorder_sig_link_no_perm_major', $asset->name, $asset->id, $old_parent->name, $old_parent->id);
1987  $this->_error('AMAP0045', $reordering_errors);
1988  } else if (!$minwa) {
1989  $reordering_errors = translate('cannot_reorder_sig_link_no_perm_minor', $asset->name, $asset->id, $old_parent->name, $old_parent->id);
1990  $this->_error('AMAP0045', $reordering_errors);
1991  }
1992 
1993  }
1994 
1995  if (!$GLOBALS['SQ_SYSTEM']->am->moveLinkPos($link_info['linkid'], $new_parent_pos)) {
1996  return;
1997  }
1998  if ($new_parent_pos <= $link_info['sort_order']) {
1999  $new_parent_pos++;
2000  }
2001  $success_node = $responses->addChild('success');
2002  $success_node->addAttribute('linkid', $link_info['linkid']);
2003  $success_node->addAttribute('assetid', $assetid);
2004 
2005  /* output when reordering
2006  <responses>
2007  <success linkid="64" assetid="55" />
2008  </responses>
2009  */
2010 
2011  }//end foreach
2012 
2013  // if we have only one link, and we cant move it to the parent we dont continue further
2014  if (count($assets) == 1 && count(reset($assets)) == 1) {
2015  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$input->asset[0]->attributes()->assetid);
2016  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset(urldecode((string)$input->asset[0]->attributes()->parentid));
2017  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById((string)$input->asset[0]->attributes()->linkid);
2018  $link_type = array_get_index($link, 'link_type', SQ_LINK_TYPE_1);
2019  $value = array_get_index($link, 'value', '');
2020  $dependant = array_get_index($link, 'is_dependant', '0');
2021  $exclusive = array_get_index($link, 'is_exclusive', '0');
2022  $sort_order = (string)$input->attributes()->to_parent_pos;
2023  $asset->prepareLink($new_parent, 'minor', $link_type, $value, $sort_order, $dependant, $exclusive);
2024  $new_parent->prepareLink($asset, 'major', $link_type, $value, $sort_order, $dependant, $exclusive);
2025  $can_create = $new_parent->canCreateLink($asset, $link_type, $exclusive);
2026  if ($can_create !== TRUE) {
2027  if ($can_create === FALSE) {
2028  $this->_error('HIPO0020', $asset->id, $new_parent->id);
2029  } else {
2030  $this->_error('AMAP0018', $can_create);
2031  }
2032  return;
2033  }
2034  }
2035 
2036 
2037  // Only run the HIPO if assets need to be moved from one parent to another
2038  if (count($assets) > 0) {
2040  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
2041 
2042  $vars = Array(
2043  'link_action' => 'move',
2044  'assets' => $assets,
2045  'reordered_assets' => $reordered_assets,
2046  'to_parent_assetid' => $new_parent->id,
2047  'to_parent_pos' => $new_parent_pos,
2048  );
2049 
2050  $hh->queueHipo('hipo_job_create_links', $vars);
2052 
2053  // check for any HIPOs that have been queued
2054  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
2055 
2056  $url = $hh->runQueuedJobs('Javascript: function closeWindow() { setTimeout(\'window.close()\', 500); } closeWindow();');
2057 
2058  if (!empty($url)) {
2059  $hipo_node = $responses->addChild('url', htmlentities($url, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
2060  $hipo_node->addAttribute('js_function', 'asset_map_popup');
2061  }
2062  }
2063 
2064  /* EXAMPLE of ouput
2065  <responses>
2066  <url js_function="asset_map_popup">http://mysite.com/colivar_dev/_admin/?SQ_ACTION=hipo&amp;hipo_source_code_name=hipo_job_create_links-f457c545a9ded88f18ecee47145a72c0</url>
2067  </responses>
2068  */
2069 
2070  $this->_send($responses);
2071 
2072  }//end _moveAssets()
2073 
2074 
2090  function _cloneAssets(&$input)
2091  {
2092 
2093  /* input example
2094  <?xml version="1.0"?>
2095  <command action="clone" to_parent_assetid="38" to_parent_pos="0">
2096  <asset assetid="39" linkid="39" parentid="1"/>
2097  </command>
2098  */
2099 
2100  $output = simplexml_load_string('<xml></xml>');
2101  $responses = $output->addChild('responses');
2102 
2103  $response_count = 0;
2104 
2105  // Make sure urlencoded assetids are restored correctly in xml
2106  $input = $this->_fixUrlencodedAssetids($input);
2107 
2108  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$input->attributes()->to_parent_assetid);
2109 
2110  if (is_null($new_parent)) {
2111  $this->_error('AMAP0035', $input->attributes()->to_parent_assetid);
2112  return;
2113  }
2114 
2115  $assets = $assets_with_sort_order = Array();
2116 
2117  foreach ($input->children() as $asset_node) {
2118  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$asset_node->attributes()->assetid);
2119  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset(urldecode((string)$asset_node->attributes()->parentid));
2120  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById((string)$asset_node->attributes()->linkid, $old_parent->id);
2121 
2122  if (is_null($old_parent)) {
2123  $this->_error('AMAP0036', (string)$asset_node->attributes()->parentid);
2124  return;
2125  }
2126 
2127  if (empty($link)) {
2128  $this->_error('AMAP0037', (string)$asset_node->attributes()->linkid);
2129  return;
2130  }
2131 
2132  if (is_null($asset)) {
2133  $this->_error('AMAP0038', (string)$asset_node->attributes()->assetid);
2134  return;
2135  }
2136 
2137  // check to see if the root asset chosen can be cloned
2138  if (!$asset->canClone()) {
2139  $this->_error('AMAP0039', $asset->name, (ucwords(str_replace('_', ' ', $asset->type()))));
2140  return;
2141  }
2142 
2143  // instead to putting the assets direstly in the array let the index be of the sort order
2144  // This will help us squashing bug #5940 Cloning multiple assets sorts them backwards under parent
2145  $assets_with_sort_order[$link['sort_order']][$asset->id] = Array(
2146  'linkid' => $link['linkid'],
2147  'parentid' => $old_parent->id,
2148  );
2149 
2150  }//end foreach
2151 
2152  // once we have allt he assets to clone now do the
2153  // sorting of array elements based on the sort_order
2154  ksort($assets_with_sort_order);
2155 
2156  foreach ($assets_with_sort_order as $sorted_assets) {
2157  foreach ($sorted_assets as $asset_id => $asset_info){
2158  $assets[$asset_id] = $asset_info;
2159  }//end foreach
2160  }//end foreach
2161 
2162  // if we have only one asset. if we cant clone it under the new parent we dont continue further
2163  if (count($assets) == 1) {
2164  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$input->asset->attributes()->assetid);
2165  $link_type = SQ_LINK_TYPE_1;
2166  $value = '';
2167  $dependant = FALSE;
2168  $exclusive = FALSE;
2169  $sort_order = (string)$input->attributes()->to_parent_pos;
2170  $asset->prepareLink($new_parent, 'minor', $link_type, $value, $sort_order, $dependant, $exclusive);
2171  $new_parent->prepareLink($asset, 'major', $link_type, $value, $sort_order, $dependant, $exclusive);
2172  $can_create = $GLOBALS['SQ_SYSTEM']->am->canLinkToType($new_parent, $asset->type(), $link_type, $dependant, $exclusive);
2173  if ($can_create !== TRUE) {
2174  $this->_error('AMAP0044', $can_create);
2175  return;
2176  }
2177  }
2178 
2179  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
2180  $vars = Array(
2181  'assets' => $assets,
2182  'to_parent_assetid' => $new_parent->id,
2183  'to_parent_pos' => ((int)$input->attributes()->to_parent_pos)+1,
2184  );
2185 
2186  $hh->queueHipo('hipo_job_clone_assets', $vars);
2187 
2188  // check for any HIPOs that have been queued
2189  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
2190 
2191  $url = $hh->runQueuedJobs('Javascript: function closeWindow() { setTimeout(\'window.close()\', 500); } closeWindow();');
2192 
2193  if (!empty($url)) {
2194  $url_tree = $responses->addChild('url', htmlentities($url, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
2195  $url_tree->addAttribute('js_function', 'asset_map_popup');
2196  }
2197 
2198  /* example of output
2199  <responses>
2200  <url js_function="asset_map_popup">http://mysite/colivar/_admin/?SQ_ACTION=hipo&amp;hipo_source_code_name=hipo_job_clone_assets-66f041e16a60928b05a7e228a89c3799</url>
2201  </responses>
2202  */
2203 
2204  $this->_send($responses);
2205 
2206  }//end _cloneAssets()
2207 
2208 
2224  function _newLinks(&$input)
2225  {
2226  /* input example
2227  <?xml version="1.0"?>
2228  <command action="new link" to_parent_assetid="38" to_parent_pos="0">
2229  <asset assetid="39" linkid="39" parentid="1"/>
2230  </command>
2231  */
2232 
2233  $output = simplexml_load_string('<xml></xml>');
2234  $responses = $output->addChild('responses');
2235 
2236  $response_count = 0;
2237 
2238  // Make sure urlencoded assetids are restored correctly in xml
2239  $input = $this->_fixUrlencodedAssetids($input);
2240 
2241  $new_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$input->attributes()->to_parent_assetid);
2242 
2243  if (is_null($new_parent)) {
2244  $this->_error('AMAP0040', (string)$input->attributes()->to_parent_assetid);
2245  return;
2246  }
2247 
2248  $assets = Array();
2249 
2250  foreach ($input->asset as $asset_node) {
2251  $old_parent = $GLOBALS['SQ_SYSTEM']->am->getAsset(urldecode((string)$asset_node->attributes()->parentid));
2252  $link = $GLOBALS['SQ_SYSTEM']->am->getLinkById((string)$asset_node->attributes()->linkid);
2253  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
2254 
2255  if (is_null($old_parent)) {
2256  $this->_error('AMAP0041', (string)$asset_node->attributes()->parentid);
2257  return;
2258  }
2259 
2260  if ($trash_folder->id == ((string)$input->attributes()->to_parent_assetid)) {
2261  $this->_error('AMAP0043');
2262  return;
2263  }
2264 
2265  $link_type = array_get_index($link, 'link_type', SQ_LINK_TYPE_1);
2266 
2267  $assets[(string)$asset_node->attributes()->assetid] = Array(
2268  'linkid' => (string)$asset_node->attributes()->linkid,
2269  'link_type' => $link_type,
2270  'parentid' => $old_parent->id,
2271  );
2272  }
2273 
2274  // if we have only one asset. if we cant link it under the new parent we dont continue further
2275  if (count($assets) == 1) {
2276  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset((string)$input->asset->attributes()->assetid);
2277  $link_type = SQ_LINK_TYPE_1;
2278  $value = '';
2279  $dependant = FALSE;
2280  $exclusive = FALSE;
2281  $sort_order = (string)$input->attributes()->to_parent_pos;
2282  $asset->prepareLink($new_parent, 'minor', $link_type, $value, $sort_order, $dependant, $exclusive);
2283  $new_parent->prepareLink($asset, 'major', $link_type, $value, $sort_order, $dependant, $exclusive);
2284  $can_create = $new_parent->canCreateLink($asset, $link_type, $exclusive);
2285  if ($can_create !== TRUE) {
2286  if ($can_create === FALSE) {
2287  $this->_error('HIPO0021', "$asset->name (#$asset->id)", "$new_parent->name (#$new_parent->id)");
2288  } else {
2289  $this->_error('AMAP0011', $can_create);
2290  }
2291  return;
2292  }
2293  }
2294 
2295  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
2296  $vars = Array(
2297  'link_action' => 'create',
2298  'assets' => $assets,
2299  'to_parent_assetid' => $new_parent->id,
2300  'to_parent_pos' => (string)$input->attributes()->to_parent_pos,
2301  );
2302  $hh->queueHipo('hipo_job_create_links', $vars);
2303 
2304  // check for any HIPOs that have been queued
2305  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
2306 
2307  $url = $hh->runQueuedJobs('Javascript: function closeWindow() { setTimeout(\'window.close()\', 500); } closeWindow();');
2308 
2309  if (!empty($url)) {
2310  $url_tree = $responses->addChild('url', htmlentities($url, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET));
2311  $url_tree->addAttribute('js_function', 'asset_map_popup');
2312  }
2313 
2314  /* example of output
2315  <?xml version="1.0"?>
2316  <responses>
2317  <url js_function="asset_map_popup">http://mysite.com/colivar/_admin/?SQ_ACTION=hipo&amp;hipo_source_code_name=hipo_job_create_links-66f041e16a60928b05a7e228a89c3799</url>
2318  </responses>
2319  */
2320  $this->_send($responses);
2321 
2322  }//end _newLinks()
2323 
2324 
2334  private function _fixUrlencodedAssetids($input)
2335  {
2336  // Construct a new input object with attribute values correctly escaped
2337  $temp_input = new SimpleXMLElement('<command></command>');
2338 
2339  foreach($input->attributes() as $attr_name => $attr_value) {
2340  // Ensure no url friendly values exists for assetids
2341  if ($attr_name == 'to_parent_assetid') {
2342  $attr_value = urldecode($attr_value);
2343  }
2344  $temp_input->addAttribute($attr_name, $attr_value);
2345  }
2346 
2347  foreach($input->asset as $asset) {
2348  $new_child = $temp_input->addChild('asset', '');
2349  foreach($asset->attributes() as $attr_name => $attr_value) {
2350  if ($attr_name == 'assetid') {
2351  $attr_value = urldecode($attr_value);
2352  }//end if
2353  $new_child->addAttribute($attr_name, $attr_value);
2354  }//end foreach
2355  }//end foreach
2356 
2357  return $temp_input;
2358 
2359  }//end _fixUrlencodedAssetids()
2360 
2361 
2362 }//end class
2363 
2364 ?>